Skip to content

Commit 36ccb98

Browse files
committed
etcm-74 added checkpoint block number methods to appStateStorage
1 parent 6a35748 commit 36ccb98

File tree

2 files changed

+129
-14
lines changed

2 files changed

+129
-14
lines changed
Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.iohk.ethereum.db.storage
22

3+
import java.math.BigInteger
4+
35
import io.iohk.ethereum.db.dataSource.{DataSource, DataSourceBatchUpdate}
46
import io.iohk.ethereum.db.storage.AppStateStorage._
57

@@ -8,18 +10,15 @@ import io.iohk.ethereum.db.storage.AppStateStorage._
810
* Key: see AppStateStorage.Keys
911
* Value: stored string value
1012
*/
11-
class AppStateStorage(val dataSource: DataSource) extends TransactionalKeyValueStorage[Key, Value]{
12-
type T = AppStateStorage
13+
class AppStateStorage(val dataSource: DataSource) extends TransactionalKeyValueStorage[Key, Value] {
1314

1415
val namespace: IndexedSeq[Byte] = Namespaces.AppStateNamespace
15-
def keySerializer: Key => IndexedSeq[Byte] = _.name.getBytes
16+
def keySerializer: Key => IndexedSeq[Byte] = _.getBytes
1617
def valueSerializer: String => IndexedSeq[Byte] = _.getBytes
1718
def valueDeserializer: IndexedSeq[Byte] => String = (valueBytes: IndexedSeq[Byte]) => new String(valueBytes.toArray)
1819

19-
protected def apply(dataSource: DataSource): AppStateStorage = new AppStateStorage(dataSource)
20-
2120
def getBestBlockNumber(): BigInt =
22-
BigInt(get(Keys.BestBlockNumber).getOrElse("0"))
21+
getBigInt(Keys.BestBlockNumber)
2322

2423
def putBestBlockNumber(bestBlockNumber: BigInt): DataSourceBatchUpdate =
2524
put(Keys.BestBlockNumber, bestBlockNumber.toString)
@@ -31,27 +30,48 @@ class AppStateStorage(val dataSource: DataSource) extends TransactionalKeyValueS
3130
put(Keys.FastSyncDone, true.toString)
3231

3332
def getEstimatedHighestBlock(): BigInt =
34-
BigInt(get(Keys.EstimatedHighestBlock).getOrElse("0"))
33+
getBigInt(Keys.EstimatedHighestBlock)
3534

3635
def putEstimatedHighestBlock(n: BigInt): DataSourceBatchUpdate =
3736
put(Keys.EstimatedHighestBlock, n.toString)
3837

3938
def getSyncStartingBlock(): BigInt =
40-
BigInt(get(Keys.SyncStartingBlock).getOrElse("0"))
39+
getBigInt(Keys.SyncStartingBlock)
4140

4241
def putSyncStartingBlock(n: BigInt): DataSourceBatchUpdate =
4342
put(Keys.SyncStartingBlock, n.toString)
43+
44+
private def getBigInt(key: Key): BigInt = {
45+
get(key).map(BigInt(_)).getOrElse(BigInt(BigInteger.ZERO))
46+
}
47+
48+
/**
49+
* It is safe to return zero in case of not having any checkpoint block,
50+
* because we assume that genesis block is a kinda stable checkpoint block (without real checkpoint)
51+
*
52+
* @return Latest CheckpointBlock Number
53+
*/
54+
def getLatestCheckpointBlockNumber(): BigInt =
55+
getBigInt(Keys.LatestCheckpointBlockNumber)
56+
57+
def removeLatestCheckpointBlockNumber(): DataSourceBatchUpdate = {
58+
update(toRemove = Seq(Keys.LatestCheckpointBlockNumber), toUpsert = Nil)
59+
}
60+
61+
def putLatestCheckpointBlockNumber(latestCheckpointBlockNumber: BigInt): DataSourceBatchUpdate = {
62+
update(Nil, Seq(Keys.LatestCheckpointBlockNumber -> latestCheckpointBlockNumber.toString))
63+
}
4464
}
4565

4666
object AppStateStorage {
67+
type Key = String
4768
type Value = String
4869

49-
case class Key private (name: String)
50-
5170
object Keys {
52-
val BestBlockNumber = Key("BestBlockNumber")
53-
val FastSyncDone = Key("FastSyncDone")
54-
val EstimatedHighestBlock = Key("EstimatedHighestBlock")
55-
val SyncStartingBlock = Key("SyncStartingBlock")
71+
val BestBlockNumber = "BestBlockNumber"
72+
val FastSyncDone = "FastSyncDone"
73+
val EstimatedHighestBlock = "EstimatedHighestBlock"
74+
val SyncStartingBlock = "SyncStartingBlock"
75+
val LatestCheckpointBlockNumber = "LatestCheckpointBlockNumber"
5676
}
5777
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package io.iohk.ethereum.db.storage
2+
3+
import io.iohk.ethereum.ObjectGenerators
4+
import io.iohk.ethereum.db.dataSource.EphemDataSource
5+
import org.scalatest.WordSpec
6+
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
7+
8+
class AppStateStorageSpec
9+
extends WordSpec
10+
with ScalaCheckPropertyChecks
11+
with ObjectGenerators {
12+
13+
"AppStateStorage" should {
14+
15+
"insert and get best block number properly" in new Fixtures {
16+
forAll(ObjectGenerators.bigIntGen) { bestBlockNumber =>
17+
val storage = newAppStateStorage()
18+
storage.putBestBlockNumber(bestBlockNumber).commit()
19+
20+
assert(storage.getBestBlockNumber() == bestBlockNumber)
21+
}
22+
}
23+
24+
"get zero as best block number when storage is empty" in new Fixtures {
25+
assert(newAppStateStorage().getBestBlockNumber() == 0)
26+
}
27+
28+
"insert and get fast sync done properly" in new Fixtures {
29+
val storage = newAppStateStorage()
30+
storage.fastSyncDone().commit()
31+
32+
assert(storage.isFastSyncDone())
33+
}
34+
35+
"get fast sync done false when storage is empty" in new Fixtures {
36+
assert(!newAppStateStorage().isFastSyncDone())
37+
}
38+
39+
"insert and get estimated highest block properly" in new Fixtures {
40+
forAll(ObjectGenerators.bigIntGen) { estimatedHighestBlock =>
41+
val storage = newAppStateStorage()
42+
storage.putEstimatedHighestBlock(estimatedHighestBlock).commit()
43+
44+
assert(storage.getEstimatedHighestBlock() == estimatedHighestBlock)
45+
}
46+
}
47+
48+
"get zero as estimated highest block when storage is empty" in new Fixtures {
49+
assert(newAppStateStorage().getEstimatedHighestBlock() == 0)
50+
}
51+
52+
"insert and get sync starting block properly" in new Fixtures {
53+
forAll(ObjectGenerators.bigIntGen) { syncStartingBlock =>
54+
val storage = newAppStateStorage()
55+
storage.putSyncStartingBlock(syncStartingBlock).commit()
56+
57+
assert(storage.getSyncStartingBlock() == syncStartingBlock)
58+
}
59+
}
60+
61+
"get zero as sync starting block when storage is empty" in new Fixtures {
62+
assert(newAppStateStorage().getSyncStartingBlock() == 0)
63+
}
64+
65+
"update and remove latest checkpoint block number properly" in new Fixtures {
66+
forAll(ObjectGenerators.bigIntGen) { latestCheckpointBlockNumber =>
67+
val storage = newAppStateStorage()
68+
69+
storage.putLatestCheckpointBlockNumber(latestCheckpointBlockNumber).commit()
70+
assert(storage.getLatestCheckpointBlockNumber() == latestCheckpointBlockNumber)
71+
72+
storage.removeLatestCheckpointBlockNumber().commit()
73+
assert(storage.getLatestCheckpointBlockNumber() == 0)
74+
}
75+
}
76+
77+
"update checkpoint block number and get it properly" in new Fixtures {
78+
forAll(ObjectGenerators.bigIntGen) { latestCheckpointBlockNumber =>
79+
val storage = newAppStateStorage()
80+
storage.putLatestCheckpointBlockNumber(latestCheckpointBlockNumber).commit()
81+
82+
assert(storage.getLatestCheckpointBlockNumber() == latestCheckpointBlockNumber)
83+
}
84+
}
85+
86+
"get zero as checkpoint block number when storage is empty" in new Fixtures {
87+
assert(newAppStateStorage().getBestBlockNumber() == 0)
88+
}
89+
}
90+
91+
trait Fixtures {
92+
def newAppStateStorage(): AppStateStorage = new AppStateStorage(EphemDataSource())
93+
}
94+
95+
}

0 commit comments

Comments
 (0)