Skip to content

Commit 30fdf98

Browse files
committed
Merge remote-tracking branch 'origin/develop' into ETCM-167-discovery-part3
2 parents cc066dd + 3b2198e commit 30fdf98

File tree

17 files changed

+277
-137
lines changed

17 files changed

+277
-137
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class ContractTest extends AnyFlatSpec with Matchers {
2626
//block only with ether transfers
2727
val blockValidation = new BlockValidation(consensus, blockchain, BlockQueue(blockchain, syncConfig))
2828
val blockExecution = new BlockExecution(blockchain, blockchainConfig, consensus.blockPreparator, blockValidation)
29-
blockExecution.executeBlock(fixtures.blockByNumber(1)) shouldBe noErrors
29+
blockExecution.executeAndValidateBlock(fixtures.blockByNumber(1)) shouldBe noErrors
3030
}
3131

3232
it should "deploy contract" in new ScenarioSetup {
@@ -37,7 +37,7 @@ class ContractTest extends AnyFlatSpec with Matchers {
3737
//contract creation
3838
val blockValidation = new BlockValidation(consensus, blockchain, BlockQueue(blockchain, syncConfig))
3939
val blockExecution = new BlockExecution(blockchain, blockchainConfig, consensus.blockPreparator, blockValidation)
40-
blockExecution.executeBlock(fixtures.blockByNumber(2)) shouldBe noErrors
40+
blockExecution.executeAndValidateBlock(fixtures.blockByNumber(2)) shouldBe noErrors
4141
}
4242

4343
it should "execute contract call" in new ScenarioSetup {
@@ -48,7 +48,7 @@ class ContractTest extends AnyFlatSpec with Matchers {
4848
//block with ether transfers and contract call
4949
val blockValidation = new BlockValidation(consensus, blockchain, BlockQueue(blockchain, syncConfig))
5050
val blockExecution = new BlockExecution(blockchain, blockchainConfig, consensus.blockPreparator, blockValidation)
51-
blockExecution.executeBlock(fixtures.blockByNumber(3)) shouldBe noErrors
51+
blockExecution.executeAndValidateBlock(fixtures.blockByNumber(3)) shouldBe noErrors
5252
}
5353

5454
it should "execute contract that pays 2 accounts" in new ScenarioSetup {
@@ -59,6 +59,6 @@ class ContractTest extends AnyFlatSpec with Matchers {
5959
//block contains contract paying 2 accounts
6060
val blockValidation = new BlockValidation(consensus, blockchain, BlockQueue(blockchain, syncConfig))
6161
val blockExecution = new BlockExecution(blockchain, blockchainConfig, consensus.blockPreparator, blockValidation)
62-
blockExecution.executeBlock(fixtures.blockByNumber(3)) shouldBe noErrors
62+
blockExecution.executeAndValidateBlock(fixtures.blockByNumber(3)) shouldBe noErrors
6363
}
6464
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class ECIP1017Test extends AnyFlatSpec with Matchers {
7676
val blockchain = BlockchainImpl(storages)
7777
val blockValidation = new BlockValidation(consensus, blockchain, BlockQueue(blockchain, syncConfig))
7878
val blockExecution = new BlockExecution(blockchain, blockchainConfig, consensus.blockPreparator, blockValidation)
79-
blockExecution.executeBlock(fixtures.blockByNumber(blockToExecute)) shouldBe noErrors
79+
blockExecution.executeAndValidateBlock(fixtures.blockByNumber(blockToExecute)) shouldBe noErrors
8080
}
8181
}
8282

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class ForksTest extends AnyFlatSpec with Matchers {
6767
val blockchain = BlockchainImpl(storages)
6868
val blockValidation = new BlockValidation(consensus, blockchain, BlockQueue(blockchain, syncConfig))
6969
val blockExecution = new BlockExecution(blockchain, blockchainConfig, consensus.blockPreparator, blockValidation)
70-
blockExecution.executeBlock(fixtures.blockByNumber(blockToExecute)) shouldBe noErrors
70+
blockExecution.executeAndValidateBlock(fixtures.blockByNumber(blockToExecute)) shouldBe noErrors
7171
}
7272
}
7373

src/main/scala/io/iohk/ethereum/db/dataSource/RocksDbDataSource.scala

Lines changed: 59 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package io.iohk.ethereum.db.dataSource
22

33
import java.util.concurrent.locks.ReentrantReadWriteLock
4-
4+
import io.iohk.ethereum.utils.Logger
55
import cats.effect.Resource
66
import io.iohk.ethereum.db.dataSource.DataSource._
7-
import io.iohk.ethereum.db.dataSource.RocksDbDataSource.{IterationError, IterationFinished}
7+
import io.iohk.ethereum.db.dataSource.RocksDbDataSource._
88
import io.iohk.ethereum.utils.TryWithResources.withResources
99
import monix.eval.Task
1010
import monix.reactive.Observable
1111
import org.rocksdb._
12-
import org.slf4j.LoggerFactory
1312

1413
import scala.collection.mutable
1514
import scala.util.control.NonFatal
@@ -22,9 +21,8 @@ class RocksDbDataSource(
2221
private var cfOptions: ColumnFamilyOptions,
2322
private var nameSpaces: Seq[Namespace],
2423
private var handles: Map[Namespace, ColumnFamilyHandle]
25-
) extends DataSource {
26-
27-
private val logger = LoggerFactory.getLogger("rocks-db")
24+
) extends DataSource
25+
with Logger {
2826

2927
@volatile
3028
private var isClosed = false
@@ -37,16 +35,20 @@ class RocksDbDataSource(
3735
* @return the value associated with the passed key.
3836
*/
3937
override def get(namespace: Namespace, key: Key): Option[Value] = {
40-
assureNotClosed()
41-
RocksDbDataSource.dbLock.readLock().lock()
38+
dbLock.readLock().lock()
4239
try {
40+
assureNotClosed()
4341
Option(db.get(handles(namespace), readOptions, key.toArray))
4442
} catch {
45-
case NonFatal(e) =>
46-
logger.error(s"Not found associated value to a namespace: $namespace and a key: $key, cause: {}", e.getMessage)
47-
throw new RuntimeException(e)
43+
case error: RocksDbDataSourceClosedException =>
44+
throw error
45+
case NonFatal(error) =>
46+
throw RocksDbDataSourceException(
47+
s"Not found associated value to a namespace: $namespace and a key: $key",
48+
error
49+
)
4850
} finally {
49-
RocksDbDataSource.dbLock.readLock().unlock()
51+
dbLock.readLock().unlock()
5052
}
5153
}
5254

@@ -59,23 +61,24 @@ class RocksDbDataSource(
5961
* @return the value associated with the passed key.
6062
*/
6163
override def getOptimized(namespace: Namespace, key: Array[Byte]): Option[Array[Byte]] = {
62-
assureNotClosed()
63-
RocksDbDataSource.dbLock.readLock().lock()
64+
dbLock.readLock().lock()
6465
try {
66+
assureNotClosed()
6567
Option(db.get(handles(namespace), readOptions, key))
6668
} catch {
67-
case NonFatal(e) =>
68-
logger.error(s"Not found associated value to a key: $key, cause: {}", e.getMessage)
69-
throw new RuntimeException(e)
69+
case error: RocksDbDataSourceClosedException =>
70+
throw error
71+
case NonFatal(error) =>
72+
throw RocksDbDataSourceException(s"Not found associated value to a key: $key", error)
7073
} finally {
71-
RocksDbDataSource.dbLock.readLock().unlock()
74+
dbLock.readLock().unlock()
7275
}
7376
}
7477

7578
override def update(dataSourceUpdates: Seq[DataUpdate]): Unit = {
76-
assureNotClosed()
77-
RocksDbDataSource.dbLock.readLock().lock()
79+
dbLock.writeLock().lock()
7880
try {
81+
assureNotClosed()
7982
withResources(new WriteOptions()) { writeOptions =>
8083
withResources(new WriteBatch()) { batch =>
8184
dataSourceUpdates.foreach {
@@ -95,14 +98,12 @@ class RocksDbDataSource(
9598
}
9699
}
97100
} catch {
98-
case NonFatal(e) =>
99-
logger.error(
100-
s"DataSource not updated, cause: {}",
101-
e.getMessage
102-
)
103-
throw new RuntimeException(e)
101+
case error: RocksDbDataSourceClosedException =>
102+
throw error
103+
case NonFatal(error) =>
104+
throw RocksDbDataSourceException(s"DataSource not updated", error)
104105
} finally {
105-
RocksDbDataSource.dbLock.readLock().unlock()
106+
dbLock.writeLock().unlock()
106107
}
107108
}
108109

@@ -139,12 +140,13 @@ class RocksDbDataSource(
139140
}
140141

141142
/**
143+
* This function is used only for tests.
142144
* This function updates the DataSource by deleting all the (key-value) pairs in it.
143145
*/
144146
override def clear(): Unit = {
145147
destroy()
146-
logger.debug(s"About to create new DataSource for path: ${rocksDbConfig.path}")
147-
val (newDb, handles, readOptions, dbOptions, cfOptions) = RocksDbDataSource.createDB(rocksDbConfig, nameSpaces.tail)
148+
log.debug(s"About to create new DataSource for path: ${rocksDbConfig.path}")
149+
val (newDb, handles, readOptions, dbOptions, cfOptions) = createDB(rocksDbConfig, nameSpaces.tail)
148150

149151
assert(nameSpaces.size == handles.size)
150152

@@ -160,11 +162,11 @@ class RocksDbDataSource(
160162
* This function closes the DataSource, without deleting the files used by it.
161163
*/
162164
override def close(): Unit = {
163-
logger.debug(s"About to close DataSource in path: ${rocksDbConfig.path}")
164-
assureNotClosed()
165-
isClosed = true
166-
RocksDbDataSource.dbLock.writeLock().lock()
165+
log.info(s"About to close DataSource in path: ${rocksDbConfig.path}")
166+
dbLock.writeLock().lock()
167167
try {
168+
assureNotClosed()
169+
isClosed = true
168170
// There is specific order for closing rocksdb with column families descibed in
169171
// https://github.com/facebook/rocksdb/wiki/RocksJava-Basics#opening-a-database-with-column-families
170172
// 1. Free all column families handles
@@ -175,16 +177,19 @@ class RocksDbDataSource(
175177
dbOptions.close()
176178
// 3. Free column families options
177179
cfOptions.close()
180+
log.info(s"DataSource closed successfully in the path: ${rocksDbConfig.path}")
178181
} catch {
179-
case NonFatal(e) =>
180-
logger.error("Not closed the DataSource properly, cause: {}", e)
181-
throw new RuntimeException(e)
182+
case error: RocksDbDataSourceClosedException =>
183+
throw error
184+
case NonFatal(error) =>
185+
throw RocksDbDataSourceException(s"Not closed the DataSource properly", error)
182186
} finally {
183-
RocksDbDataSource.dbLock.writeLock().unlock()
187+
dbLock.writeLock().unlock()
184188
}
185189
}
186190

187191
/**
192+
* This function is used only for tests.
188193
* This function closes the DataSource, if it is not yet closed, and deletes all the files used by it.
189194
*/
190195
override def destroy(): Unit = {
@@ -193,8 +198,13 @@ class RocksDbDataSource(
193198
close()
194199
}
195200
} finally {
196-
import rocksDbConfig._
201+
destroyDB()
202+
}
203+
}
197204

205+
protected def destroyDB(): Unit = {
206+
try {
207+
import rocksDbConfig._
198208
val tableCfg = new BlockBasedTableConfig()
199209
.setBlockSize(blockSize)
200210
.setBlockCache(new ClockCache(blockCacheSize))
@@ -212,15 +222,18 @@ class RocksDbDataSource(
212222
.setIncreaseParallelism(maxThreads)
213223
.setTableFormatConfig(tableCfg)
214224

215-
logger.debug(s"About to destroy DataSource in path: $path")
225+
log.debug(s"About to destroy DataSource in path: $path")
216226
RocksDB.destroyDB(path, options)
217227
options.close()
228+
} catch {
229+
case NonFatal(error) =>
230+
throw RocksDbDataSourceException(s"Not destroyed the DataSource properly", error)
218231
}
219232
}
220233

221234
private def assureNotClosed(): Unit = {
222235
if (isClosed) {
223-
throw new IllegalStateException(s"This ${getClass.getSimpleName} has been closed")
236+
throw RocksDbDataSourceClosedException(s"This ${getClass.getSimpleName} has been closed")
224237
}
225238
}
226239

@@ -242,6 +255,9 @@ object RocksDbDataSource {
242255
case object IterationFinished extends RuntimeException
243256
case class IterationError(ex: Throwable)
244257

258+
case class RocksDbDataSourceClosedException(message: String) extends IllegalStateException(message)
259+
case class RocksDbDataSourceException(message: String, cause: Throwable) extends RuntimeException(message, cause)
260+
245261
/**
246262
* The rocksdb implementation acquires a lock from the operating system to prevent misuse
247263
*/
@@ -296,6 +312,9 @@ object RocksDbDataSource {
296312
options,
297313
cfOpts
298314
)
315+
} catch {
316+
case NonFatal(error) =>
317+
throw RocksDbDataSourceException(s"Not created the DataSource properly", error)
299318
} finally {
300319
RocksDbDataSource.dbLock.writeLock().unlock()
301320
}

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package io.iohk.ethereum.jsonrpc
22

33
import akka.util.ByteString
4-
import io.iohk.ethereum.domain.{Block, BlockHeader, BlockBody}
4+
import io.iohk.ethereum.crypto.ECDSASignature
5+
import io.iohk.ethereum.domain.{Block, BlockBody, BlockHeader}
6+
7+
case class CheckpointResponse(signatures: Seq[ECDSASignature], signers: Seq[ByteString])
58

69
case class BlockResponse(
710
number: BigInt,
@@ -21,6 +24,8 @@ case class BlockResponse(
2124
gasLimit: BigInt,
2225
gasUsed: BigInt,
2326
timestamp: BigInt,
27+
checkpoint: Option[CheckpointResponse],
28+
treasuryOptOut: Option[Boolean],
2429
transactions: Either[Seq[ByteString], Seq[TransactionResponse]],
2530
uncles: Seq[ByteString]
2631
)
@@ -41,6 +46,12 @@ object BlockResponse {
4146
else
4247
Left(block.body.transactionList.map(_.hash))
4348

49+
val checkpoint = block.header.checkpoint.map { checkpoint =>
50+
val signers = checkpoint.signatures.flatMap(_.publicKey(block.header.parentHash))
51+
52+
CheckpointResponse(checkpoint.signatures, signers)
53+
}
54+
4455
BlockResponse(
4556
number = block.header.number,
4657
hash = if (pendingBlock) None else Some(block.header.hash),
@@ -59,6 +70,8 @@ object BlockResponse {
5970
gasLimit = block.header.gasLimit,
6071
gasUsed = block.header.gasUsed,
6172
timestamp = block.header.unixTimestamp,
73+
checkpoint = checkpoint,
74+
treasuryOptOut = block.header.treasuryOptOut,
6275
transactions = transactions,
6376
uncles = block.body.uncleNodesList.map(_.hash)
6477
)

0 commit comments

Comments
 (0)