[Feat] Upgrade Spotless from 6.16 to 6.25 (Breaking change) (#1068)

* remove 2nd subproject.spotless

* make linea-sequencer lint command, do lint command of child projects

* bump spotless to 6.25

* bump ktlint to 0.50.0

* run spotlessApply

* fix spotlessCheck for testing-tools:app

* spotless apply for many kt projects

* spotless apply for many kt projects

* set trailing comma to false in .editorconfig for kt files

* add more .editorconfig settings

* Revert "add more .editorconfig settings"

This reverts commit bd9f040f950930a662e8f815c5d504b3b4403703.

* Revert "set trailing comma to false in .editorconfig for kt files"

This reverts commit 4bcc08aa295c4da8d0bef2c75cf3fe621e0a00ae.

* empty
This commit is contained in:
kyzooghost
2025-06-03 00:02:21 +10:00
committed by GitHub
parent 19735ced28
commit cce0126d90
530 changed files with 5055 additions and 4956 deletions

View File

@@ -29,7 +29,7 @@ class LineaL1FinalizationTagUpdaterPlugin : BesuPlugin {
service = LineaL1FinalizationUpdaterService( service = LineaL1FinalizationUpdaterService(
vertx, vertx,
cliOptions.getConfig(), cliOptions.getConfig(),
LineaBesuEngineBlockTagUpdater(blockchainService) LineaBesuEngineBlockTagUpdater(blockchainService),
) )
service.start() service.start()
} }

View File

@@ -16,7 +16,7 @@ import kotlin.time.Duration.Companion.seconds
data class FinalizationUpdatePollerConfig( data class FinalizationUpdatePollerConfig(
val pollingInterval: Duration = 12.seconds, val pollingInterval: Duration = 12.seconds,
val blockTag: BlockParameter val blockTag: BlockParameter,
) { ) {
init { init {
require(pollingInterval >= 0.seconds) { require(pollingInterval >= 0.seconds) {
@@ -30,18 +30,18 @@ class FinalizationUpdatePoller(
private val config: FinalizationUpdatePollerConfig, private val config: FinalizationUpdatePollerConfig,
private val lineaRollup: Web3JLineaRollupSmartContractClientReadOnly, private val lineaRollup: Web3JLineaRollupSmartContractClientReadOnly,
private val finalizationHandler: (ULong) -> CompletableFuture<*>, private val finalizationHandler: (ULong) -> CompletableFuture<*>,
private val log: Logger = LogManager.getLogger(FinalizationUpdatePoller::class.java) private val log: Logger = LogManager.getLogger(FinalizationUpdatePoller::class.java),
) : PeriodicPollingService( ) : PeriodicPollingService(
vertx = vertx, vertx = vertx,
pollingIntervalMs = config.pollingInterval.inWholeMilliseconds, pollingIntervalMs = config.pollingInterval.inWholeMilliseconds,
log = log log = log,
) { ) {
private val lastFinalizationRef: AtomicReference<ULong> = AtomicReference(null) private val lastFinalizationRef: AtomicReference<ULong> = AtomicReference(null)
override fun action(): SafeFuture<*> { override fun action(): SafeFuture<*> {
return AsyncRetryer.retry( return AsyncRetryer.retry(
vertx, vertx,
backoffDelay = config.pollingInterval backoffDelay = config.pollingInterval,
) { ) {
lineaRollup.finalizedL2BlockNumber(config.blockTag) lineaRollup.finalizedL2BlockNumber(config.blockTag)
.thenCompose { lineaFinalizedBlockNumber -> .thenCompose { lineaFinalizedBlockNumber ->
@@ -61,7 +61,7 @@ class FinalizationUpdatePoller(
if (error.cause is UnsupportedOperationException) { if (error.cause is UnsupportedOperationException) {
log.error( log.error(
"\"setFinalizedBlock\" and \"setSafeBlock\" methods are not supported in the hosting Besu client, " + "\"setFinalizedBlock\" and \"setSafeBlock\" methods are not supported in the hosting Besu client, " +
"the poller will stop now, please check the Besu client's settings" "the poller will stop now, please check the Besu client's settings",
) )
super.stop() super.stop()
} else { } else {

View File

@@ -28,7 +28,7 @@ class LineaBesuEngineBlockTagUpdater(private val blockchainService: BlockchainSe
log.info( log.info(
"Linea safe/finalized block update: blockNumber={} blockHash={}", "Linea safe/finalized block update: blockNumber={} blockHash={}",
finalizedBlockNumber, finalizedBlockNumber,
blockHash blockHash,
) )
blockchainService.setSafeBlock(blockHash) blockchainService.setSafeBlock(blockHash)
blockchainService.setFinalizedBlock(blockHash) blockchainService.setFinalizedBlock(blockHash)
@@ -40,7 +40,7 @@ class LineaBesuEngineBlockTagUpdater(private val blockchainService: BlockchainSe
log.error( log.error(
"Linea safe/finalized block update failure: Method not supported or not enabled for PoS network: " + "Linea safe/finalized block update failure: Method not supported or not enabled for PoS network: " +
"setFinalizedBlock and setSafeBlock", "setFinalizedBlock and setSafeBlock",
e e,
) )
throw e throw e
} catch (e: Exception) { } catch (e: Exception) {
@@ -54,7 +54,7 @@ class LineaBesuEngineBlockTagUpdater(private val blockchainService: BlockchainSe
} }
override fun lineaUpdateFinalizedBlockV1( override fun lineaUpdateFinalizedBlockV1(
finalizedBlockNumber: Long finalizedBlockNumber: Long,
) { ) {
val updateSuccess = setFinalizedAndSafeBlock(finalizedBlockNumber) val updateSuccess = setFinalizedAndSafeBlock(finalizedBlockNumber)
log.debug("Linea safe/finalized block update: blockNumber={} success={}", finalizedBlockNumber, updateSuccess) log.debug("Linea safe/finalized block update: blockNumber={} success={}", finalizedBlockNumber, updateSuccess)
@@ -62,10 +62,10 @@ class LineaBesuEngineBlockTagUpdater(private val blockchainService: BlockchainSe
} }
class LineaL1FinalizationUpdater( class LineaL1FinalizationUpdater(
private val engineBlockTagUpdater: EngineBlockTagUpdater private val engineBlockTagUpdater: EngineBlockTagUpdater,
) { ) {
fun handleL1Finalization( fun handleL1Finalization(
finalizedBlockNumber: ULong finalizedBlockNumber: ULong,
): CompletableFuture<Unit> { ): CompletableFuture<Unit> {
runCatching { runCatching {
engineBlockTagUpdater engineBlockTagUpdater
@@ -80,28 +80,28 @@ class LineaL1FinalizationUpdater(
class LineaL1FinalizationUpdaterService( class LineaL1FinalizationUpdaterService(
vertx: Vertx, vertx: Vertx,
config: PluginConfig, config: PluginConfig,
engineBlockTagUpdater: EngineBlockTagUpdater engineBlockTagUpdater: EngineBlockTagUpdater,
) : LongRunningService { ) : LongRunningService {
private val web3j = Web3j.build( private val web3j = Web3j.build(
HttpService( HttpService(
config.l1RpcEndpoint.toString(), config.l1RpcEndpoint.toString(),
okHttpClientBuilder(LogManager.getLogger("clients.l1")).build() okHttpClientBuilder(LogManager.getLogger("clients.l1")).build(),
) ),
) )
private val lineaRollup = Web3JLineaRollupSmartContractClientReadOnly( private val lineaRollup = Web3JLineaRollupSmartContractClientReadOnly(
contractAddress = config.l1SmartContractAddress.toHexString(), contractAddress = config.l1SmartContractAddress.toHexString(),
web3j = web3j web3j = web3j,
) )
private val updater = LineaL1FinalizationUpdater(engineBlockTagUpdater) private val updater = LineaL1FinalizationUpdater(engineBlockTagUpdater)
private val poller = FinalizationUpdatePoller( private val poller = FinalizationUpdatePoller(
vertx, vertx,
FinalizationUpdatePollerConfig( FinalizationUpdatePollerConfig(
pollingInterval = config.l1PollingInterval, pollingInterval = config.l1PollingInterval,
blockTag = BlockParameter.Tag.FINALIZED blockTag = BlockParameter.Tag.FINALIZED,
), ),
lineaRollup, lineaRollup,
updater::handleL1Finalization, updater::handleL1Finalization,
LogManager.getLogger(FinalizationUpdatePoller::class.java) LogManager.getLogger(FinalizationUpdatePoller::class.java),
) )
override fun start(): CompletableFuture<Unit> { override fun start(): CompletableFuture<Unit> {

View File

@@ -11,7 +11,7 @@ import kotlin.time.toKotlinDuration
data class PluginConfig( data class PluginConfig(
val l1SmartContractAddress: Address, val l1SmartContractAddress: Address,
val l1RpcEndpoint: URL, val l1RpcEndpoint: URL,
val l1PollingInterval: kotlin.time.Duration val l1PollingInterval: kotlin.time.Duration,
) { ) {
init { init {
require(l1PollingInterval >= 1.seconds) { "Polling interval=$l1PollingInterval must be greater that 1s." } require(l1PollingInterval >= 1.seconds) { "Polling interval=$l1PollingInterval must be greater that 1s." }
@@ -23,21 +23,21 @@ class PluginCliOptions {
names = ["--plugin-linea-l1-smart-contract-address"], names = ["--plugin-linea-l1-smart-contract-address"],
description = ["L1 smart contract address"], description = ["L1 smart contract address"],
required = true, required = true,
converter = [AddressConverter::class] converter = [AddressConverter::class],
) )
lateinit var l1SmartContractAddress: Address lateinit var l1SmartContractAddress: Address
@CommandLine.Option( @CommandLine.Option(
names = ["--plugin-linea-l1-rpc-endpoint"], names = ["--plugin-linea-l1-rpc-endpoint"],
description = ["L1 RPC endpoint"], description = ["L1 RPC endpoint"],
required = true required = true,
) )
lateinit var l1RpcEndpoint: String lateinit var l1RpcEndpoint: String
@CommandLine.Option( @CommandLine.Option(
names = ["--plugin-linea-l1-polling-interval"], names = ["--plugin-linea-l1-polling-interval"],
description = ["L1 polling interval"], description = ["L1 polling interval"],
required = false required = false,
) )
var l1PollingInterval: Duration = Duration.ofSeconds(12) var l1PollingInterval: Duration = Duration.ofSeconds(12)
@@ -45,14 +45,14 @@ class PluginCliOptions {
return PluginConfig( return PluginConfig(
l1SmartContractAddress = l1SmartContractAddress, l1SmartContractAddress = l1SmartContractAddress,
l1RpcEndpoint = URI(l1RpcEndpoint).toURL(), l1RpcEndpoint = URI(l1RpcEndpoint).toURL(),
l1PollingInterval = l1PollingInterval.toKotlinDuration() l1PollingInterval = l1PollingInterval.toKotlinDuration(),
) )
} }
class AddressConverter : CommandLine.ITypeConverter<Address> { class AddressConverter : CommandLine.ITypeConverter<Address> {
override fun convert(value: String): Address { override fun convert(value: String): Address {
return Address.fromHexString(value) ?: throw CommandLine.TypeConversionException( return Address.fromHexString(value) ?: throw CommandLine.TypeConversionException(
"Invalid address: $value" "Invalid address: $value",
) )
} }
} }

View File

@@ -11,7 +11,7 @@ import kotlin.time.Duration.Companion.seconds
class FakeEngineBlockTagUpdater : EngineBlockTagUpdater { class FakeEngineBlockTagUpdater : EngineBlockTagUpdater {
override fun lineaUpdateFinalizedBlockV1( override fun lineaUpdateFinalizedBlockV1(
finalizedBlockNumber: Long finalizedBlockNumber: Long,
) { ) {
println("Linea finalized block update: blockNumber=$finalizedBlockNumber") println("Linea finalized block update: blockNumber=$finalizedBlockNumber")
} }
@@ -23,7 +23,7 @@ fun main() {
val config = PluginConfig( val config = PluginConfig(
l1RpcEndpoint = URI("https://mainnet.infura.io/v3/$infuraAppKey").toURL(), l1RpcEndpoint = URI("https://mainnet.infura.io/v3/$infuraAppKey").toURL(),
l1SmartContractAddress = Address.fromHexString("0xd19d4B5d358258f05D7B411E21A1460D11B0876F"), l1SmartContractAddress = Address.fromHexString("0xd19d4B5d358258f05D7B411E21A1460D11B0876F"),
l1PollingInterval = 1.seconds l1PollingInterval = 1.seconds,
) )
val service = LineaL1FinalizationUpdaterService(vertx, config, FakeEngineBlockTagUpdater()) val service = LineaL1FinalizationUpdaterService(vertx, config, FakeEngineBlockTagUpdater())
service.start().get() service.start().get()

View File

@@ -33,6 +33,15 @@ licenseReport {
] ]
} }
// Make the parent project's spotlessCheck depend on all subproject spotlessCheck tasks
afterEvaluate {
if (tasks.findByName('spotlessCheck')) {
spotlessCheck.dependsOn subprojects.collect { subproject ->
subproject.tasks.matching { task -> task.name == 'spotlessCheck' }
}
}
}
build { build {
dependsOn checkLicense dependsOn checkLicense
} }

View File

@@ -6,7 +6,7 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture
data class StateRecoveryStatus( data class StateRecoveryStatus(
val headBlockNumber: ULong, val headBlockNumber: ULong,
val stateRecoverStartBlockNumber: ULong? val stateRecoverStartBlockNumber: ULong?,
) )
interface ExecutionLayerClient { interface ExecutionLayerClient {
fun getBlockNumberAndHash(blockParameter: BlockParameter): SafeFuture<BlockNumberAndHash> fun getBlockNumberAndHash(blockParameter: BlockParameter): SafeFuture<BlockNumberAndHash>

View File

@@ -24,20 +24,20 @@ class InMemoryRecoveryStatus : RecoveryStatusPersistence {
} }
class FileBasedRecoveryStatusPersistence( class FileBasedRecoveryStatusPersistence(
filePath: Path filePath: Path,
) : RecoveryStatusPersistence { ) : RecoveryStatusPersistence {
// A little future proofing in case we need to change the file format in the future // A little future proofing in case we need to change the file format in the future
private enum class FileVersion { private enum class FileVersion {
V1 // note: do not rename because it will fail to parse the file if already written V1, // note: do not rename because it will fail to parse the file if already written
} }
private data class RecoveryStatusEnvelopeDto( private data class RecoveryStatusEnvelopeDto(
val version: FileVersion, val version: FileVersion,
val recoveryStatus: RecoveryStatusV1Dto? val recoveryStatus: RecoveryStatusV1Dto?,
) )
private data class RecoveryStatusV1Dto( private data class RecoveryStatusV1Dto(
val recoveryStartBlockNumber: ULong val recoveryStartBlockNumber: ULong,
) )
private val objectMapper = jacksonObjectMapper() private val objectMapper = jacksonObjectMapper()
private val file = filePath.toFile() private val file = filePath.toFile()
@@ -46,8 +46,8 @@ class FileBasedRecoveryStatusPersistence(
private fun saveToFile(status: RecoveryStatusV1Dto?) { private fun saveToFile(status: RecoveryStatusV1Dto?) {
file.writeText( file.writeText(
objectMapper.writeValueAsString( objectMapper.writeValueAsString(
RecoveryStatusEnvelopeDto(FileVersion.V1, status) RecoveryStatusEnvelopeDto(FileVersion.V1, status),
) ),
) )
} }

View File

@@ -13,7 +13,7 @@ class FileRecoveryStatusPersistenceTest {
@Test @Test
fun `should return null when no recovery start block number is saved`( fun `should return null when no recovery start block number is saved`(
@TempDir tempDir: Path @TempDir tempDir: Path,
) { ) {
val recoveryStatusPersistence = FileBasedRecoveryStatusPersistence(tempDir.resolve("recovery-status.json")) val recoveryStatusPersistence = FileBasedRecoveryStatusPersistence(tempDir.resolve("recovery-status.json"))
assertThat(recoveryStatusPersistence.getRecoveryStartBlockNumber()).isNull() assertThat(recoveryStatusPersistence.getRecoveryStartBlockNumber()).isNull()
@@ -21,7 +21,7 @@ class FileRecoveryStatusPersistenceTest {
@Test @Test
fun `should return the saved recovery start block number`( fun `should return the saved recovery start block number`(
@TempDir tempDir: Path @TempDir tempDir: Path,
) { ) {
FileBasedRecoveryStatusPersistence(tempDir.resolve("recovery-status.json")) FileBasedRecoveryStatusPersistence(tempDir.resolve("recovery-status.json"))
.also { persistence -> .also { persistence ->
@@ -46,7 +46,7 @@ class FileRecoveryStatusPersistenceTest {
@Test @Test
fun `shall throw when it cannot create the file`( fun `shall throw when it cannot create the file`(
@TempDir tempDir: Path @TempDir tempDir: Path,
) { ) {
val dirWithoutWritePermissions = tempDir.resolve("dir-without-write-permissions") val dirWithoutWritePermissions = tempDir.resolve("dir-without-write-permissions")
@@ -64,7 +64,7 @@ class FileRecoveryStatusPersistenceTest {
@Test @Test
fun `should throw error when file version is not supported`( fun `should throw error when file version is not supported`(
@TempDir tempDir: Path @TempDir tempDir: Path,
) { ) {
val invalidJsonPayload = """ val invalidJsonPayload = """
{ {

View File

@@ -9,7 +9,7 @@ data class BlockHeaderFromL1RecoveredData(
val coinbase: ByteArray, val coinbase: ByteArray,
val blockTimestamp: Instant, val blockTimestamp: Instant,
val gasLimit: ULong, val gasLimit: ULong,
val difficulty: ULong val difficulty: ULong,
) { ) {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
@@ -51,7 +51,7 @@ data class BlockHeaderFromL1RecoveredData(
data class BlockFromL1RecoveredData( data class BlockFromL1RecoveredData(
val header: BlockHeaderFromL1RecoveredData, val header: BlockHeaderFromL1RecoveredData,
val transactions: List<TransactionFromL1RecoveredData> val transactions: List<TransactionFromL1RecoveredData>,
) { ) {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true

View File

@@ -14,12 +14,12 @@ data class TransactionFromL1RecoveredData(
val to: ByteArray?, val to: ByteArray?,
val value: BigInteger, val value: BigInteger,
val data: ByteArray?, val data: ByteArray?,
val accessList: List<AccessTuple>? val accessList: List<AccessTuple>?,
) { ) {
data class AccessTuple( data class AccessTuple(
val address: ByteArray, val address: ByteArray,
val storageKeys: List<ByteArray> val storageKeys: List<ByteArray>,
) { ) {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true

View File

@@ -24,18 +24,18 @@ interface BlobDecompressorAndDeserializer {
*/ */
fun decompress( fun decompress(
startBlockNumber: ULong, startBlockNumber: ULong,
blobs: List<ByteArray> blobs: List<ByteArray>,
): SafeFuture<List<BlockFromL1RecoveredData>> ): SafeFuture<List<BlockFromL1RecoveredData>>
} }
data class BlockHeaderStaticFields( data class BlockHeaderStaticFields(
val coinbase: ByteArray, val coinbase: ByteArray,
val gasLimit: ULong = 2_000_000_000UL, val gasLimit: ULong = 2_000_000_000UL,
val difficulty: ULong = 2UL val difficulty: ULong = 2UL,
) { ) {
companion object { companion object {
val localDev = BlockHeaderStaticFields( val localDev = BlockHeaderStaticFields(
coinbase = "0x6d976c9b8ceee705d4fe8699b44e5eb58242f484".decodeHex() coinbase = "0x6d976c9b8ceee705d4fe8699b44e5eb58242f484".decodeHex(),
) )
} }
@@ -69,11 +69,11 @@ class BlobDecompressorToDomainV1(
val staticFields: BlockHeaderStaticFields, val staticFields: BlockHeaderStaticFields,
val vertx: Vertx, val vertx: Vertx,
val decoder: BinaryDecoder<Block> = BesuRlpBlobDecoder, val decoder: BinaryDecoder<Block> = BesuRlpBlobDecoder,
val logger: Logger = LogManager.getLogger(BlobDecompressorToDomainV1::class.java) val logger: Logger = LogManager.getLogger(BlobDecompressorToDomainV1::class.java),
) : BlobDecompressorAndDeserializer { ) : BlobDecompressorAndDeserializer {
override fun decompress( override fun decompress(
startBlockNumber: ULong, startBlockNumber: ULong,
blobs: List<ByteArray> blobs: List<ByteArray>,
): SafeFuture<List<BlockFromL1RecoveredData>> { ): SafeFuture<List<BlockFromL1RecoveredData>> {
var blockNumber = startBlockNumber var blockNumber = startBlockNumber
val startTime = Clock.System.now() val startTime = Clock.System.now()
@@ -89,7 +89,7 @@ class BlobDecompressorToDomainV1(
coinbase = staticFields.coinbase, coinbase = staticFields.coinbase,
blockTimestamp = Instant.fromEpochSeconds(block.header.timestamp), blockTimestamp = Instant.fromEpochSeconds(block.header.timestamp),
gasLimit = this.staticFields.gasLimit, gasLimit = this.staticFields.gasLimit,
difficulty = this.staticFields.difficulty difficulty = this.staticFields.difficulty,
) )
val transactions = block.body.transactions.map { transaction -> val transactions = block.body.transactions.map { transaction ->
TransactionFromL1RecoveredData( TransactionFromL1RecoveredData(
@@ -106,14 +106,14 @@ class BlobDecompressorToDomainV1(
accessList = transaction.accessList.getOrNull()?.map { accessTuple -> accessList = transaction.accessList.getOrNull()?.map { accessTuple ->
TransactionFromL1RecoveredData.AccessTuple( TransactionFromL1RecoveredData.AccessTuple(
address = accessTuple.address.toArray(), address = accessTuple.address.toArray(),
storageKeys = accessTuple.storageKeys.map { it.toArray() } storageKeys = accessTuple.storageKeys.map { it.toArray() },
) )
} },
) )
} }
BlockFromL1RecoveredData( BlockFromL1RecoveredData(
header = header, header = header,
transactions = transactions transactions = transactions,
) )
} }
}.thenPeek { }.thenPeek {
@@ -122,7 +122,7 @@ class BlobDecompressorToDomainV1(
"blobs decompressed and serialized: duration={} blobsCount={} blocks={}", "blobs decompressed and serialized: duration={} blobsCount={} blocks={}",
endTime - startTime, endTime - startTime,
blobs.size, blobs.size,
CommonDomainFunctions.blockIntervalString(startBlockNumber, blockNumber - 1UL) CommonDomainFunctions.blockIntervalString(startBlockNumber, blockNumber - 1UL),
) )
} }
} }
@@ -130,7 +130,7 @@ class BlobDecompressorToDomainV1(
private fun decodeBlocksAsync(blocksRLP: ByteArray): SafeFuture<List<Block>> { private fun decodeBlocksAsync(blocksRLP: ByteArray): SafeFuture<List<Block>> {
return vertx.executeBlocking( return vertx.executeBlocking(
Callable { RLP.decodeList(blocksRLP).map(decoder::decode) }, Callable { RLP.decodeList(blocksRLP).map(decoder::decode) },
false false,
) )
.onFailure(logger::error) .onFailure(logger::error)
.toSafeFuture() .toSafeFuture()

View File

@@ -10,7 +10,7 @@ import kotlin.time.Duration.Companion.seconds
data class ImportResult( data class ImportResult(
val blockNumber: ULong, val blockNumber: ULong,
val zkStateRootHash: ByteArray val zkStateRootHash: ByteArray,
) { ) {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
@@ -39,7 +39,7 @@ class BlockImporterAndStateVerifierV1(
private val vertx: Vertx, private val vertx: Vertx,
private val elClient: ExecutionLayerClient, private val elClient: ExecutionLayerClient,
private val stateManagerClient: StateManagerClientV1, private val stateManagerClient: StateManagerClientV1,
private val stateManagerImportTimeoutPerBlock: Duration private val stateManagerImportTimeoutPerBlock: Duration,
) : BlockImporterAndStateVerifier { ) : BlockImporterAndStateVerifier {
override fun importBlocks(blocks: List<BlockFromL1RecoveredData>): SafeFuture<ImportResult> { override fun importBlocks(blocks: List<BlockFromL1RecoveredData>): SafeFuture<ImportResult> {
val sortedBlocks = blocks.sortedBy { it.header.blockNumber } val sortedBlocks = blocks.sortedBy { it.header.blockNumber }
@@ -49,20 +49,20 @@ class BlockImporterAndStateVerifierV1(
.thenCompose { .thenCompose {
getBlockStateRootHash( getBlockStateRootHash(
blockNumber = lastBlockNumber, blockNumber = lastBlockNumber,
timeout = stateManagerImportTimeoutPerBlock.times(blocks.size) timeout = stateManagerImportTimeoutPerBlock.times(blocks.size),
) )
} }
.thenApply { stateRootHash -> .thenApply { stateRootHash ->
ImportResult( ImportResult(
blockNumber = lastBlockNumber, blockNumber = lastBlockNumber,
zkStateRootHash = stateRootHash zkStateRootHash = stateRootHash,
) )
} }
} }
private fun getBlockStateRootHash( private fun getBlockStateRootHash(
blockNumber: ULong, blockNumber: ULong,
timeout: Duration timeout: Duration,
): SafeFuture<ByteArray> { ): SafeFuture<ByteArray> {
return AsyncRetryer return AsyncRetryer
.retry( .retry(
@@ -70,7 +70,7 @@ class BlockImporterAndStateVerifierV1(
backoffDelay = 1.seconds, backoffDelay = 1.seconds,
timeout = timeout, timeout = timeout,
stopRetriesPredicate = { headBlockNumber -> headBlockNumber >= blockNumber }, stopRetriesPredicate = { headBlockNumber -> headBlockNumber >= blockNumber },
action = { stateManagerClient.rollupGetHeadBlockNumber() } action = { stateManagerClient.rollupGetHeadBlockNumber() },
) )
.thenCompose { .thenCompose {
stateManagerClient.rollupGetStateMerkleProof(BlockInterval(blockNumber, blockNumber)) stateManagerClient.rollupGetStateMerkleProof(BlockInterval(blockNumber, blockNumber))

View File

@@ -12,7 +12,7 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture
data class DataSubmittedV3( data class DataSubmittedV3(
val parentShnarf: ByteArray, val parentShnarf: ByteArray,
val shnarf: ByteArray, val shnarf: ByteArray,
val finalStateRootHash: ByteArray val finalStateRootHash: ByteArray,
) { ) {
companion object { companion object {
val topic = "0x55f4c645c36aa5cd3f443d6be44d7a7a5df9d2100d7139dfc69d4289ee072319" val topic = "0x55f4c645c36aa5cd3f443d6be44d7a7a5df9d2100d7139dfc69d4289ee072319"
@@ -22,9 +22,9 @@ data class DataSubmittedV3(
event = DataSubmittedV3( event = DataSubmittedV3(
parentShnarf = ethLog.data.sliceOf32(0), parentShnarf = ethLog.data.sliceOf32(0),
shnarf = ethLog.topics[1], shnarf = ethLog.topics[1],
finalStateRootHash = ethLog.data.sliceOf32(1) finalStateRootHash = ethLog.data.sliceOf32(1),
), ),
log = ethLog log = ethLog,
) )
} }
} }
@@ -62,7 +62,7 @@ data class DataFinalizedV3(
override val endBlockNumber: ULong, override val endBlockNumber: ULong,
val shnarf: ByteArray, val shnarf: ByteArray,
val parentStateRootHash: ByteArray, val parentStateRootHash: ByteArray,
val finalStateRootHash: ByteArray val finalStateRootHash: ByteArray,
) : BlockInterval { ) : BlockInterval {
companion object { companion object {
val topic = "0xa0262dc79e4ccb71ceac8574ae906311ae338aa4a2044fd4ec4b99fad5ab60cb" val topic = "0xa0262dc79e4ccb71ceac8574ae906311ae338aa4a2044fd4ec4b99fad5ab60cb"
@@ -81,9 +81,9 @@ data class DataFinalizedV3(
endBlockNumber = ethLog.topics[2].toULongFromLast8Bytes(), endBlockNumber = ethLog.topics[2].toULongFromLast8Bytes(),
shnarf = ethLog.topics[3], shnarf = ethLog.topics[3],
parentStateRootHash = dataBytes.sliceOf32(sliceNumber = 0), parentStateRootHash = dataBytes.sliceOf32(sliceNumber = 0),
finalStateRootHash = dataBytes.sliceOf32(sliceNumber = 1) finalStateRootHash = dataBytes.sliceOf32(sliceNumber = 1),
), ),
log = ethLog log = ethLog,
) )
} }
} }
@@ -124,17 +124,17 @@ data class DataFinalizedV3(
data class FinalizationAndDataEventsV3( data class FinalizationAndDataEventsV3(
val dataSubmittedEvents: List<EthLogEvent<DataSubmittedV3>>, val dataSubmittedEvents: List<EthLogEvent<DataSubmittedV3>>,
val dataFinalizedEvent: EthLogEvent<DataFinalizedV3> val dataFinalizedEvent: EthLogEvent<DataFinalizedV3>,
) )
interface LineaRollupSubmissionEventsClient { interface LineaRollupSubmissionEventsClient {
fun findFinalizationAndDataSubmissionV3Events( fun findFinalizationAndDataSubmissionV3Events(
fromL1BlockNumber: BlockParameter, fromL1BlockNumber: BlockParameter,
finalizationStartBlockNumber: ULong finalizationStartBlockNumber: ULong,
): SafeFuture<FinalizationAndDataEventsV3?> ): SafeFuture<FinalizationAndDataEventsV3?>
fun findFinalizationAndDataSubmissionV3EventsContainingL2BlockNumber( fun findFinalizationAndDataSubmissionV3EventsContainingL2BlockNumber(
fromL1BlockNumber: BlockParameter, fromL1BlockNumber: BlockParameter,
l2BlockNumber: ULong l2BlockNumber: ULong,
): SafeFuture<FinalizationAndDataEventsV3?> ): SafeFuture<FinalizationAndDataEventsV3?>
} }

View File

@@ -13,7 +13,7 @@ class LineaSubmissionEventsClientImpl(
private val logsSearcher: EthLogsSearcher, private val logsSearcher: EthLogsSearcher,
private val smartContractAddress: String, private val smartContractAddress: String,
private val l1LatestSearchBlock: BlockParameter = BlockParameter.Tag.FINALIZED, private val l1LatestSearchBlock: BlockParameter = BlockParameter.Tag.FINALIZED,
private val logsBlockChunkSize: Int private val logsBlockChunkSize: Int,
) : LineaRollupSubmissionEventsClient { ) : LineaRollupSubmissionEventsClient {
init { init {
require(logsBlockChunkSize > 0) { "logsBlockChunkSize=$logsBlockChunkSize must be greater than 0" } require(logsBlockChunkSize > 0) { "logsBlockChunkSize=$logsBlockChunkSize must be greater than 0" }
@@ -21,7 +21,7 @@ class LineaSubmissionEventsClientImpl(
private fun findDataFinalizedEventContainingBlock( private fun findDataFinalizedEventContainingBlock(
fromBlock: BlockParameter, fromBlock: BlockParameter,
l2BlockNumber: ULong l2BlockNumber: ULong,
): SafeFuture<EthLogEvent<DataFinalizedV3>?> { ): SafeFuture<EthLogEvent<DataFinalizedV3>?> {
return logsSearcher.findLog( return logsSearcher.findLog(
fromBlock = fromBlock, fromBlock = fromBlock,
@@ -36,18 +36,18 @@ class LineaSubmissionEventsClientImpl(
l2BlockNumber > event.endBlockNumber -> SearchDirection.FORWARD l2BlockNumber > event.endBlockNumber -> SearchDirection.FORWARD
else -> null else -> null
} }
} },
).thenApply { it?.let { DataFinalizedV3.fromEthLog(it) } } ).thenApply { it?.let { DataFinalizedV3.fromEthLog(it) } }
} }
override fun findFinalizationAndDataSubmissionV3Events( override fun findFinalizationAndDataSubmissionV3Events(
fromL1BlockNumber: BlockParameter, fromL1BlockNumber: BlockParameter,
finalizationStartBlockNumber: ULong finalizationStartBlockNumber: ULong,
): SafeFuture<FinalizationAndDataEventsV3?> { ): SafeFuture<FinalizationAndDataEventsV3?> {
return findDataFinalizedV3Event( return findDataFinalizedV3Event(
fromL1BlockNumber = fromL1BlockNumber, fromL1BlockNumber = fromL1BlockNumber,
toL1BlockNumber = l1LatestSearchBlock, toL1BlockNumber = l1LatestSearchBlock,
startBlockNumber = finalizationStartBlockNumber startBlockNumber = finalizationStartBlockNumber,
) )
.thenCompose { finalizationEvent -> .thenCompose { finalizationEvent ->
finalizationEvent finalizationEvent
@@ -63,7 +63,7 @@ class LineaSubmissionEventsClientImpl(
override fun findFinalizationAndDataSubmissionV3EventsContainingL2BlockNumber( override fun findFinalizationAndDataSubmissionV3EventsContainingL2BlockNumber(
fromL1BlockNumber: BlockParameter, fromL1BlockNumber: BlockParameter,
l2BlockNumber: ULong l2BlockNumber: ULong,
): SafeFuture<FinalizationAndDataEventsV3?> { ): SafeFuture<FinalizationAndDataEventsV3?> {
return findDataFinalizedEventContainingBlock(fromL1BlockNumber, l2BlockNumber) return findDataFinalizedEventContainingBlock(fromL1BlockNumber, l2BlockNumber)
.thenCompose { finalizationEvent -> .thenCompose { finalizationEvent ->
@@ -82,7 +82,7 @@ class LineaSubmissionEventsClientImpl(
fromL1BlockNumber: BlockParameter, fromL1BlockNumber: BlockParameter,
toL1BlockNumber: BlockParameter, toL1BlockNumber: BlockParameter,
startBlockNumber: ULong? = null, startBlockNumber: ULong? = null,
endBlockNumber: ULong? = null endBlockNumber: ULong? = null,
): SafeFuture<EthLogEvent<DataFinalizedV3>?> { ): SafeFuture<EthLogEvent<DataFinalizedV3>?> {
assert(startBlockNumber != null || endBlockNumber != null) { assert(startBlockNumber != null || endBlockNumber != null) {
"Either startBlockNumber or endBlockNumber must be provided" "Either startBlockNumber or endBlockNumber must be provided"
@@ -104,8 +104,8 @@ class LineaSubmissionEventsClientImpl(
topics = listOf( topics = listOf(
DataFinalizedV3.topic, DataFinalizedV3.topic,
startBlockNumber?.toHexStringUInt256(), startBlockNumber?.toHexStringUInt256(),
endBlockNumber?.toHexStringUInt256() endBlockNumber?.toHexStringUInt256(),
) ),
).thenCompose { rawLogs -> ).thenCompose { rawLogs ->
val finalizedEvents = rawLogs.map(DataFinalizedV3::fromEthLog) val finalizedEvents = rawLogs.map(DataFinalizedV3::fromEthLog)
@@ -122,7 +122,7 @@ class LineaSubmissionEventsClientImpl(
} }
private fun findAggregationDataSubmittedV3Events( private fun findAggregationDataSubmittedV3Events(
finalizationEvent: EthLogEvent<DataFinalizedV3> finalizationEvent: EthLogEvent<DataFinalizedV3>,
): SafeFuture<List<EthLogEvent<DataSubmittedV3>>> { ): SafeFuture<List<EthLogEvent<DataSubmittedV3>>> {
val dataEvents = mutableListOf<EthLogEvent<DataSubmittedV3>>() val dataEvents = mutableListOf<EthLogEvent<DataSubmittedV3>>()
val futureResult = SafeFuture<List<EthLogEvent<DataSubmittedV3>>>() val futureResult = SafeFuture<List<EthLogEvent<DataSubmittedV3>>>()
@@ -140,7 +140,7 @@ class LineaSubmissionEventsClientImpl(
findDataSubmittedV3EventByShnarf( findDataSubmittedV3EventByShnarf(
fromL1BlockParameter = BlockParameter.Tag.EARLIEST, fromL1BlockParameter = BlockParameter.Tag.EARLIEST,
tol1BlockParameter = dataSubmission.log.blockNumber.toLong().toBlockParameter(), tol1BlockParameter = dataSubmission.log.blockNumber.toLong().toBlockParameter(),
shnarf = dataSubmission.event.parentShnarf shnarf = dataSubmission.event.parentShnarf,
).thenPeek(::fetchParentDataSubmission) ).thenPeek(::fetchParentDataSubmission)
} }
} }
@@ -148,7 +148,7 @@ class LineaSubmissionEventsClientImpl(
getDataSubmittedV3EventByShnarf( getDataSubmittedV3EventByShnarf(
fromL1BlockParameter = BlockParameter.Tag.EARLIEST, fromL1BlockParameter = BlockParameter.Tag.EARLIEST,
tol1BlockParameter = finalizationEvent.log.blockNumber.toLong().toBlockParameter(), tol1BlockParameter = finalizationEvent.log.blockNumber.toLong().toBlockParameter(),
shnarf = finalizationEvent.event.shnarf shnarf = finalizationEvent.event.shnarf,
).thenPeek(::fetchParentDataSubmission) ).thenPeek(::fetchParentDataSubmission)
return futureResult return futureResult
@@ -157,7 +157,7 @@ class LineaSubmissionEventsClientImpl(
private fun getDataSubmittedV3EventByShnarf( private fun getDataSubmittedV3EventByShnarf(
fromL1BlockParameter: BlockParameter, fromL1BlockParameter: BlockParameter,
tol1BlockParameter: BlockParameter, tol1BlockParameter: BlockParameter,
shnarf: ByteArray shnarf: ByteArray,
): SafeFuture<EthLogEvent<DataSubmittedV3>> { ): SafeFuture<EthLogEvent<DataSubmittedV3>> {
return findDataSubmittedV3EventByShnarf(fromL1BlockParameter, tol1BlockParameter, shnarf) return findDataSubmittedV3EventByShnarf(fromL1BlockParameter, tol1BlockParameter, shnarf)
.thenApply { event -> .thenApply { event ->
@@ -168,7 +168,7 @@ class LineaSubmissionEventsClientImpl(
private fun findDataSubmittedV3EventByShnarf( private fun findDataSubmittedV3EventByShnarf(
fromL1BlockParameter: BlockParameter, fromL1BlockParameter: BlockParameter,
tol1BlockParameter: BlockParameter, tol1BlockParameter: BlockParameter,
shnarf: ByteArray shnarf: ByteArray,
): SafeFuture<EthLogEvent<DataSubmittedV3>?> { ): SafeFuture<EthLogEvent<DataSubmittedV3>?> {
return logsSearcher return logsSearcher
.getLogs( .getLogs(
@@ -177,8 +177,8 @@ class LineaSubmissionEventsClientImpl(
address = smartContractAddress, address = smartContractAddress,
topics = listOf( topics = listOf(
DataSubmittedV3.topic, DataSubmittedV3.topic,
shnarf.encodeHex() shnarf.encodeHex(),
) ),
) )
.thenApply { rawLogs -> .thenApply { rawLogs ->
val events = rawLogs.map(DataSubmittedV3::fromEthLog) val events = rawLogs.map(DataSubmittedV3::fromEthLog)

View File

@@ -12,28 +12,28 @@ import kotlin.time.Duration.Companion.seconds
class LookBackBlockHashesFetcher( class LookBackBlockHashesFetcher(
private val vertx: Vertx, private val vertx: Vertx,
private val elClient: ExecutionLayerClient, private val elClient: ExecutionLayerClient,
private val submissionsFetcher: SubmissionsFetchingTask private val submissionsFetcher: SubmissionsFetchingTask,
) { ) {
fun getLookBackHashes( fun getLookBackHashes(
status: StateRecoveryStatus status: StateRecoveryStatus,
): SafeFuture<Map<ULong, ByteArray>> { ): SafeFuture<Map<ULong, ByteArray>> {
val intervals = lookbackFetchingIntervals( val intervals = lookbackFetchingIntervals(
headBlockNumber = status.headBlockNumber, headBlockNumber = status.headBlockNumber,
recoveryStartBlockNumber = status.stateRecoverStartBlockNumber, recoveryStartBlockNumber = status.stateRecoverStartBlockNumber,
lookbackWindow = 256UL lookbackWindow = 256UL,
) )
return SafeFuture.collectAll( return SafeFuture.collectAll(
listOf( listOf(
intervals.elInterval?.let(::getLookBackHashesFromLocalEl) ?: SafeFuture.completedFuture(emptyMap()), intervals.elInterval?.let(::getLookBackHashesFromLocalEl) ?: SafeFuture.completedFuture(emptyMap()),
intervals.l1Interval?.let(::getLookBackHashesFromL1) ?: SafeFuture.completedFuture(emptyMap()) intervals.l1Interval?.let(::getLookBackHashesFromL1) ?: SafeFuture.completedFuture(emptyMap()),
).stream() ).stream(),
) )
.thenApply { (blockHashesFromEl, blockHashesFromL1) -> blockHashesFromEl + blockHashesFromL1 } .thenApply { (blockHashesFromEl, blockHashesFromL1) -> blockHashesFromEl + blockHashesFromL1 }
} }
fun getLookBackHashesFromLocalEl( fun getLookBackHashesFromLocalEl(
blockInterval: BlockInterval blockInterval: BlockInterval,
): SafeFuture<Map<ULong, ByteArray>> { ): SafeFuture<Map<ULong, ByteArray>> {
return SafeFuture return SafeFuture
.collectAll(blockInterval.blocksRange.map { elClient.getBlockNumberAndHash(it.toBlockParameter()) }.stream()) .collectAll(blockInterval.blocksRange.map { elClient.getBlockNumberAndHash(it.toBlockParameter()) }.stream())
@@ -43,7 +43,7 @@ class LookBackBlockHashesFetcher(
} }
fun getLookBackHashesFromL1( fun getLookBackHashesFromL1(
blockInterval: BlockInterval blockInterval: BlockInterval,
): SafeFuture<Map<ULong, ByteArray>> { ): SafeFuture<Map<ULong, ByteArray>> {
return AsyncRetryer.retry( return AsyncRetryer.retry(
vertx, vertx,
@@ -51,7 +51,7 @@ class LookBackBlockHashesFetcher(
stopRetriesPredicate = { submissions -> stopRetriesPredicate = { submissions ->
submissions.isNotEmpty() && submissions.isNotEmpty() &&
submissions.last().submissionEvents.dataFinalizedEvent.event.endBlockNumber >= blockInterval.endBlockNumber submissions.last().submissionEvents.dataFinalizedEvent.event.endBlockNumber >= blockInterval.endBlockNumber
} },
) { ) {
// get the data without removing it from the queue // get the data without removing it from the queue
// it must still be in the queue until is imported to the EL // it must still be in the queue until is imported to the EL
@@ -75,7 +75,7 @@ class LookBackBlockHashesFetcher(
fun shallIncreaseQueueLimit( fun shallIncreaseQueueLimit(
availableSubmissions: List<SubmissionEventsAndData<BlockFromL1RecoveredData>>, availableSubmissions: List<SubmissionEventsAndData<BlockFromL1RecoveredData>>,
blockInterval: BlockInterval blockInterval: BlockInterval,
): Boolean { ): Boolean {
if (availableSubmissions.isEmpty()) { if (availableSubmissions.isEmpty()) {
return false return false

View File

@@ -6,7 +6,7 @@ import linea.kotlin.minusCoercingUnderflow
fun startBlockToFetchFromL1( fun startBlockToFetchFromL1(
headBlockNumber: ULong, headBlockNumber: ULong,
recoveryStartBlockNumber: ULong?, recoveryStartBlockNumber: ULong?,
lookbackWindow: ULong lookbackWindow: ULong,
): ULong { ): ULong {
if (recoveryStartBlockNumber == null) { if (recoveryStartBlockNumber == null) {
return headBlockNumber + 1UL return headBlockNumber + 1UL
@@ -19,24 +19,24 @@ fun startBlockToFetchFromL1(
data class FetchingIntervals( data class FetchingIntervals(
val elInterval: BlockInterval?, val elInterval: BlockInterval?,
val l1Interval: BlockInterval? val l1Interval: BlockInterval?,
) )
fun lookbackFetchingIntervals( fun lookbackFetchingIntervals(
headBlockNumber: ULong, headBlockNumber: ULong,
recoveryStartBlockNumber: ULong?, recoveryStartBlockNumber: ULong?,
lookbackWindow: ULong lookbackWindow: ULong,
): FetchingIntervals { ): FetchingIntervals {
if (recoveryStartBlockNumber == null || recoveryStartBlockNumber > headBlockNumber) { if (recoveryStartBlockNumber == null || recoveryStartBlockNumber > headBlockNumber) {
return FetchingIntervals( return FetchingIntervals(
l1Interval = null, l1Interval = null,
elInterval = BlockInterval(headBlockNumber.minusCoercingUnderflow(lookbackWindow - 1UL), headBlockNumber) elInterval = BlockInterval(headBlockNumber.minusCoercingUnderflow(lookbackWindow - 1UL), headBlockNumber),
) )
} }
if (headBlockNumber - lookbackWindow > recoveryStartBlockNumber) { if (headBlockNumber - lookbackWindow > recoveryStartBlockNumber) {
return FetchingIntervals( return FetchingIntervals(
l1Interval = BlockInterval(headBlockNumber.minusCoercingUnderflow(lookbackWindow - 1UL), headBlockNumber), l1Interval = BlockInterval(headBlockNumber.minusCoercingUnderflow(lookbackWindow - 1UL), headBlockNumber),
elInterval = null elInterval = null,
) )
} }
@@ -44,7 +44,7 @@ fun lookbackFetchingIntervals(
l1Interval = BlockInterval(recoveryStartBlockNumber, headBlockNumber), l1Interval = BlockInterval(recoveryStartBlockNumber, headBlockNumber),
elInterval = BlockInterval( elInterval = BlockInterval(
headBlockNumber.minusCoercingUnderflow(lookbackWindow - 1UL), headBlockNumber.minusCoercingUnderflow(lookbackWindow - 1UL),
recoveryStartBlockNumber - 1UL recoveryStartBlockNumber - 1UL,
) ),
) )
} }

View File

@@ -28,7 +28,7 @@ class StateRecoveryApp(
private val transactionDetailsClient: TransactionDetailsClient, private val transactionDetailsClient: TransactionDetailsClient,
private val blockHeaderStaticFields: BlockHeaderStaticFields, private val blockHeaderStaticFields: BlockHeaderStaticFields,
// configs // configs
private val config: Config private val config: Config,
) : LongRunningService { ) : LongRunningService {
data class Config( data class Config(
val smartContractAddress: String, val smartContractAddress: String,
@@ -43,7 +43,7 @@ class StateRecoveryApp(
* this is meant for testing purposes, not production * this is meant for testing purposes, not production
*/ */
val overridingRecoveryStartBlockNumber: ULong? = null, val overridingRecoveryStartBlockNumber: ULong? = null,
val debugForceSyncStopBlockNumber: ULong? = null val debugForceSyncStopBlockNumber: ULong? = null,
) { ) {
companion object { companion object {
val lineaMainnet = Config( val lineaMainnet = Config(
@@ -53,7 +53,7 @@ class StateRecoveryApp(
l1LatestSearchBlock = BlockParameter.Tag.FINALIZED, l1LatestSearchBlock = BlockParameter.Tag.FINALIZED,
l1PollingInterval = 12.seconds, l1PollingInterval = 12.seconds,
l1getLogsChunkSize = 10_000u, l1getLogsChunkSize = 10_000u,
executionClientPollingInterval = 2.seconds executionClientPollingInterval = 2.seconds,
) )
val lineaSepolia = Config( val lineaSepolia = Config(
smartContractAddress = "0xb218f8a4bc926cf1ca7b3423c154a0d627bdb7e5", smartContractAddress = "0xb218f8a4bc926cf1ca7b3423c154a0d627bdb7e5",
@@ -61,7 +61,7 @@ class StateRecoveryApp(
l1LatestSearchBlock = BlockParameter.Tag.FINALIZED, l1LatestSearchBlock = BlockParameter.Tag.FINALIZED,
l1PollingInterval = 12.seconds, l1PollingInterval = 12.seconds,
l1getLogsChunkSize = 10_000u, l1getLogsChunkSize = 10_000u,
executionClientPollingInterval = 2.seconds executionClientPollingInterval = 2.seconds,
) )
} }
} }
@@ -76,19 +76,19 @@ class StateRecoveryApp(
logsSearcher = ethLogsSearcher, logsSearcher = ethLogsSearcher,
smartContractAddress = config.smartContractAddress, smartContractAddress = config.smartContractAddress,
l1LatestSearchBlock = config.l1LatestSearchBlock, l1LatestSearchBlock = config.l1LatestSearchBlock,
logsBlockChunkSize = config.l1getLogsChunkSize.toInt() logsBlockChunkSize = config.l1getLogsChunkSize.toInt(),
) )
private val log = LogManager.getLogger(this::class.java) private val log = LogManager.getLogger(this::class.java)
private val blockImporterAndStateVerifier = BlockImporterAndStateVerifierV1( private val blockImporterAndStateVerifier = BlockImporterAndStateVerifierV1(
vertx = vertx, vertx = vertx,
elClient = elClient, elClient = elClient,
stateManagerClient = stateManagerClient, stateManagerClient = stateManagerClient,
stateManagerImportTimeoutPerBlock = 2.seconds stateManagerImportTimeoutPerBlock = 2.seconds,
) )
private val blobDecompressor: BlobDecompressorAndDeserializer = BlobDecompressorToDomainV1( private val blobDecompressor: BlobDecompressorAndDeserializer = BlobDecompressorToDomainV1(
decompressor = GoNativeBlobDecompressorFactory.getInstance(config.blobDecompressorVersion), decompressor = GoNativeBlobDecompressorFactory.getInstance(config.blobDecompressorVersion),
staticFields = blockHeaderStaticFields, staticFields = blockHeaderStaticFields,
vertx = vertx vertx = vertx,
) )
private val stateSynchronizerService = StateSynchronizerService( private val stateSynchronizerService = StateSynchronizerService(
vertx = vertx, vertx = vertx,
@@ -100,7 +100,7 @@ class StateRecoveryApp(
blobDecompressor = blobDecompressor, blobDecompressor = blobDecompressor,
blockImporterAndStateVerifier = blockImporterAndStateVerifier, blockImporterAndStateVerifier = blockImporterAndStateVerifier,
pollingInterval = config.l1PollingInterval, pollingInterval = config.l1PollingInterval,
debugForceSyncStopBlockNumber = config.debugForceSyncStopBlockNumber debugForceSyncStopBlockNumber = config.debugForceSyncStopBlockNumber,
) )
val stateRootMismatchFound: Boolean val stateRootMismatchFound: Boolean
get() = stateSynchronizerService.stateRootMismatchFound get() = stateSynchronizerService.stateRootMismatchFound
@@ -119,7 +119,7 @@ class StateRecoveryApp(
updateLabel, updateLabel,
newStatus.headBlockNumber, newStatus.headBlockNumber,
statusBeforeUpdate.stateRecoverStartBlockNumber, statusBeforeUpdate.stateRecoverStartBlockNumber,
newStatus.stateRecoverStartBlockNumber newStatus.stateRecoverStartBlockNumber,
) )
} }
} }
@@ -138,7 +138,7 @@ class StateRecoveryApp(
log.info( log.info(
"starting recovery mode already enabled: stateRecoverStartBlockNumber={} headBlockNumber={}", "starting recovery mode already enabled: stateRecoverStartBlockNumber={} headBlockNumber={}",
status.stateRecoverStartBlockNumber, status.stateRecoverStartBlockNumber,
status.headBlockNumber status.headBlockNumber,
) )
SafeFuture.completedFuture(Unit) SafeFuture.completedFuture(Unit)
} else { } else {
@@ -153,7 +153,7 @@ class StateRecoveryApp(
"L1 lastFinalizedBlockNumber={}", "L1 lastFinalizedBlockNumber={}",
stateRecoverStartBlockNumber, stateRecoverStartBlockNumber,
status.headBlockNumber, status.headBlockNumber,
lastFinalizedBlockNumber lastFinalizedBlockNumber,
) )
elClient.lineaEnableStateRecovery(stateRecoverStartBlockNumber) elClient.lineaEnableStateRecovery(stateRecoverStartBlockNumber)
}.thenApply { } }.thenApply { }
@@ -175,17 +175,17 @@ class StateRecoveryApp(
log.info( log.info(
"node reached recovery target block: stateRecoverStartBlockNumber={} headBlockNumber={}", "node reached recovery target block: stateRecoverStartBlockNumber={} headBlockNumber={}",
recoveryStatus.stateRecoverStartBlockNumber, recoveryStatus.stateRecoverStartBlockNumber,
recoveryStatus.headBlockNumber recoveryStatus.headBlockNumber,
) )
} else { } else {
log.info( log.info(
"waiting for node to sync until stateRecoverStartBlockNumber={} - 1, headBlockNumber={}", "waiting for node to sync until stateRecoverStartBlockNumber={} - 1, headBlockNumber={}",
recoveryStatus.stateRecoverStartBlockNumber, recoveryStatus.stateRecoverStartBlockNumber,
recoveryStatus.headBlockNumber recoveryStatus.headBlockNumber,
) )
} }
hasReachedTargetBlock hasReachedTargetBlock
} },
) { ) {
elClient.lineaGetStateRecoveryStatus() elClient.lineaGetStateRecoveryStatus()
} }

View File

@@ -22,11 +22,11 @@ class StateSynchronizerService(
private val blockImporterAndStateVerifier: BlockImporterAndStateVerifier, private val blockImporterAndStateVerifier: BlockImporterAndStateVerifier,
private val pollingInterval: Duration, private val pollingInterval: Duration,
private val debugForceSyncStopBlockNumber: ULong?, private val debugForceSyncStopBlockNumber: ULong?,
private val log: Logger = LogManager.getLogger(StateSynchronizerService::class.java) private val log: Logger = LogManager.getLogger(StateSynchronizerService::class.java),
) : PeriodicPollingService( ) : PeriodicPollingService(
vertx = vertx, vertx = vertx,
log = log, log = log,
pollingIntervalMs = pollingInterval.inWholeMilliseconds pollingIntervalMs = pollingInterval.inWholeMilliseconds,
) { ) {
@get:Synchronized @get:Synchronized
@set:Synchronized @set:Synchronized
@@ -48,7 +48,7 @@ class StateSynchronizerService(
val l2StartBlockNumberToFetchInclusive = startBlockToFetchFromL1( val l2StartBlockNumberToFetchInclusive = startBlockToFetchFromL1(
headBlockNumber = status.headBlockNumber, headBlockNumber = status.headBlockNumber,
recoveryStartBlockNumber = status.stateRecoverStartBlockNumber, recoveryStartBlockNumber = status.stateRecoverStartBlockNumber,
lookbackWindow = 256UL lookbackWindow = 256UL,
) )
this.blobsFetcherTask = SubmissionsFetchingTask( this.blobsFetcherTask = SubmissionsFetchingTask(
@@ -63,7 +63,7 @@ class StateSynchronizerService(
submissionEventsQueueLimit = 10, submissionEventsQueueLimit = 10,
compressedBlobsQueueLimit = 10, compressedBlobsQueueLimit = 10,
targetDecompressedBlobsQueueLimit = 10, targetDecompressedBlobsQueueLimit = 10,
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber,
) )
blobsFetcherTask.start() blobsFetcherTask.start()
} }
@@ -91,7 +91,7 @@ class StateSynchronizerService(
val loobackHasheFetcher = LookBackBlockHashesFetcher( val loobackHasheFetcher = LookBackBlockHashesFetcher(
vertx = vertx, vertx = vertx,
elClient = elClient, elClient = elClient,
submissionsFetcher = blobsFetcherTask submissionsFetcher = blobsFetcherTask,
) )
return this.elClient return this.elClient
@@ -116,30 +116,30 @@ class StateSynchronizerService(
if (blocksToImport.isEmpty()) { if (blocksToImport.isEmpty()) {
log.debug( log.debug(
"no blocks to import for finalization={}", "no blocks to import for finalization={}",
nexFinalization.submissionEvents.dataFinalizedEvent.event nexFinalization.submissionEvents.dataFinalizedEvent.event,
) )
return@thenCompose SafeFuture.completedFuture(Unit) return@thenCompose SafeFuture.completedFuture(Unit)
} }
importBlocksAndAssertStateroot( importBlocksAndAssertStateroot(
decompressedBlocksToImport = blocksToImport, decompressedBlocksToImport = blocksToImport,
dataFinalizedV3 = nexFinalization.submissionEvents.dataFinalizedEvent.event dataFinalizedV3 = nexFinalization.submissionEvents.dataFinalizedEvent.event,
) )
} }
.thenPeek { .thenPeek {
blobsFetcherTask.pruneQueueForElementsUpToInclusive( blobsFetcherTask.pruneQueueForElementsUpToInclusive(
nexFinalization.submissionEvents.dataFinalizedEvent.event.endBlockNumber nexFinalization.submissionEvents.dataFinalizedEvent.event.endBlockNumber,
) )
} }
} }
private fun importBlocksAndAssertStateroot( private fun importBlocksAndAssertStateroot(
decompressedBlocksToImport: List<BlockFromL1RecoveredData>, decompressedBlocksToImport: List<BlockFromL1RecoveredData>,
dataFinalizedV3: DataFinalizedV3 dataFinalizedV3: DataFinalizedV3,
): SafeFuture<Unit> { ): SafeFuture<Unit> {
val blockInterval = CommonDomainFunctions.blockIntervalString( val blockInterval = CommonDomainFunctions.blockIntervalString(
decompressedBlocksToImport.first().header.blockNumber, decompressedBlocksToImport.first().header.blockNumber,
decompressedBlocksToImport.last().header.blockNumber decompressedBlocksToImport.last().header.blockNumber,
) )
log.debug("importing blocks={} from finalization={}", blockInterval, dataFinalizedV3.intervalString()) log.debug("importing blocks={} from finalization={}", blockInterval, dataFinalizedV3.intervalString())
return blockImporterAndStateVerifier return blockImporterAndStateVerifier
@@ -151,7 +151,7 @@ class StateSynchronizerService(
} }
private fun filterOutBlocksAlreadyImportedAndBeyondStopSync( private fun filterOutBlocksAlreadyImportedAndBeyondStopSync(
blocks: List<BlockFromL1RecoveredData> blocks: List<BlockFromL1RecoveredData>,
): SafeFuture<List<BlockFromL1RecoveredData>> { ): SafeFuture<List<BlockFromL1RecoveredData>> {
return elClient.getBlockNumberAndHash(blockParameter = BlockParameter.Tag.LATEST) return elClient.getBlockNumberAndHash(blockParameter = BlockParameter.Tag.LATEST)
.thenApply { headBlock -> .thenApply { headBlock ->
@@ -165,14 +165,14 @@ class StateSynchronizerService(
private fun assertStateMatches( private fun assertStateMatches(
importResult: ImportResult, importResult: ImportResult,
finalizedV3: DataFinalizedV3 finalizedV3: DataFinalizedV3,
): SafeFuture<Unit> { ): SafeFuture<Unit> {
if (importResult.blockNumber != finalizedV3.endBlockNumber) { if (importResult.blockNumber != finalizedV3.endBlockNumber) {
log.info( log.info(
"cannot compare stateroot: last imported block={} finalization={} debugForceSyncStopBlockNumber={}", "cannot compare stateroot: last imported block={} finalization={} debugForceSyncStopBlockNumber={}",
importResult.blockNumber, importResult.blockNumber,
finalizedV3.intervalString(), finalizedV3.intervalString(),
debugForceSyncStopBlockNumber debugForceSyncStopBlockNumber,
) )
if (importResult.blockNumber == debugForceSyncStopBlockNumber) { if (importResult.blockNumber == debugForceSyncStopBlockNumber) {
// this means debugForceSyncStopBlockNumber was set and we stopped before reaching the target block // this means debugForceSyncStopBlockNumber was set and we stopped before reaching the target block
@@ -183,7 +183,7 @@ class StateSynchronizerService(
log.info( log.info(
"state recovered up to finalization={} zkStateRootHash={}", "state recovered up to finalization={} zkStateRootHash={}",
finalizedV3.intervalString(), finalizedV3.intervalString(),
importResult.zkStateRootHash.encodeHex() importResult.zkStateRootHash.encodeHex(),
) )
} else { } else {
log.error( log.error(
@@ -193,7 +193,7 @@ class StateSynchronizerService(
finalizedV3.intervalString(), finalizedV3.intervalString(),
importResult.blockNumber, importResult.blockNumber,
importResult.zkStateRootHash.encodeHex(), importResult.zkStateRootHash.encodeHex(),
finalizedV3.finalStateRootHash.encodeHex() finalizedV3.finalStateRootHash.encodeHex(),
) )
stateRootMismatchFound = true stateRootMismatchFound = true
this.stop() this.stop()

View File

@@ -18,11 +18,11 @@ internal class BlobDecompressionTask(
private val rawBlobsQueue: ConcurrentLinkedQueue<SubmissionEventsAndData<ByteArray>>, private val rawBlobsQueue: ConcurrentLinkedQueue<SubmissionEventsAndData<ByteArray>>,
private val decompressedBlocksQueue: ConcurrentLinkedQueue<SubmissionEventsAndData<BlockFromL1RecoveredData>>, private val decompressedBlocksQueue: ConcurrentLinkedQueue<SubmissionEventsAndData<BlockFromL1RecoveredData>>,
private val decompressedFinalizationQueueLimit: Supplier<Int>, private val decompressedFinalizationQueueLimit: Supplier<Int>,
private val log: Logger = LogManager.getLogger(SubmissionsFetchingTask::class.java) private val log: Logger = LogManager.getLogger(SubmissionsFetchingTask::class.java),
) : PeriodicPollingService( ) : PeriodicPollingService(
vertx = vertx, vertx = vertx,
pollingIntervalMs = pollingInterval.inWholeMilliseconds, pollingIntervalMs = pollingInterval.inWholeMilliseconds,
log = log log = log,
) { ) {
override fun action(): SafeFuture<*> { override fun action(): SafeFuture<*> {
return decompressAndDeserializeBlobs() return decompressAndDeserializeBlobs()
@@ -38,10 +38,10 @@ internal class BlobDecompressionTask(
return blobDecompressor return blobDecompressor
.decompress( .decompress(
startBlockNumber = submissionEventsAndData.submissionEvents.dataFinalizedEvent.event.startBlockNumber, startBlockNumber = submissionEventsAndData.submissionEvents.dataFinalizedEvent.event.startBlockNumber,
blobs = submissionEventsAndData.data blobs = submissionEventsAndData.data,
).thenCompose { decompressedBlocks -> ).thenCompose { decompressedBlocks ->
decompressedBlocksQueue.add( decompressedBlocksQueue.add(
SubmissionEventsAndData(submissionEventsAndData.submissionEvents, decompressedBlocks) SubmissionEventsAndData(submissionEventsAndData.submissionEvents, decompressedBlocks),
) )
decompressAndDeserializeBlobs() decompressAndDeserializeBlobs()
} }

View File

@@ -19,11 +19,11 @@ internal class BlobsFetchingTask(
private val submissionEventsQueue: ConcurrentLinkedQueue<FinalizationAndDataEventsV3>, private val submissionEventsQueue: ConcurrentLinkedQueue<FinalizationAndDataEventsV3>,
private val compressedBlobsQueue: ConcurrentLinkedQueue<SubmissionEventsAndData<ByteArray>>, private val compressedBlobsQueue: ConcurrentLinkedQueue<SubmissionEventsAndData<ByteArray>>,
private val compressedBlobsQueueLimit: Int, private val compressedBlobsQueueLimit: Int,
private val log: Logger = LogManager.getLogger(BlobsFetchingTask::class.java) private val log: Logger = LogManager.getLogger(BlobsFetchingTask::class.java),
) : PeriodicPollingService( ) : PeriodicPollingService(
vertx = vertx, vertx = vertx,
pollingIntervalMs = pollingInterval.inWholeMilliseconds, pollingIntervalMs = pollingInterval.inWholeMilliseconds,
log = log log = log,
) { ) {
override fun action(): SafeFuture<*> { override fun action(): SafeFuture<*> {
@@ -50,13 +50,13 @@ internal class BlobsFetchingTask(
} }
private fun fetchBlobsOfSubmissionEvents( private fun fetchBlobsOfSubmissionEvents(
submissionEvents: FinalizationAndDataEventsV3 submissionEvents: FinalizationAndDataEventsV3,
): SafeFuture<List<ByteArray>> { ): SafeFuture<List<ByteArray>> {
return SafeFuture.collectAll( return SafeFuture.collectAll(
submissionEvents.dataSubmittedEvents submissionEvents.dataSubmittedEvents
.map { .map {
transactionDetailsClient.getBlobVersionedHashesByTransactionHash(it.log.transactionHash) transactionDetailsClient.getBlobVersionedHashesByTransactionHash(it.log.transactionHash)
}.stream() }.stream(),
) )
.thenCompose { blobsVersionedHashesByTransaction -> .thenCompose { blobsVersionedHashesByTransaction ->
blobsFetcher.fetchBlobsByHash(blobsVersionedHashesByTransaction.flatten()) blobsFetcher.fetchBlobsByHash(blobsVersionedHashesByTransaction.flatten())

View File

@@ -24,11 +24,11 @@ internal class SubmissionEventsFetchingTask(
private val submissionEventsQueue: ConcurrentLinkedQueue<FinalizationAndDataEventsV3>, private val submissionEventsQueue: ConcurrentLinkedQueue<FinalizationAndDataEventsV3>,
private val queueLimit: Int, private val queueLimit: Int,
private val debugForceSyncStopBlockNumber: ULong?, private val debugForceSyncStopBlockNumber: ULong?,
private val log: Logger = LogManager.getLogger(SubmissionEventsFetchingTask::class.java) private val log: Logger = LogManager.getLogger(SubmissionEventsFetchingTask::class.java),
) : PeriodicPollingService( ) : PeriodicPollingService(
vertx = vertx, vertx = vertx,
pollingIntervalMs = l1PollingInterval.inWholeMilliseconds, pollingIntervalMs = l1PollingInterval.inWholeMilliseconds,
log = log log = log,
) { ) {
val latestFetchedFinalization: AtomicReference<EthLogEvent<DataFinalizedV3>> = AtomicReference(null) val latestFetchedFinalization: AtomicReference<EthLogEvent<DataFinalizedV3>> = AtomicReference(null)
@@ -38,7 +38,7 @@ internal class SubmissionEventsFetchingTask(
) { ) {
log.debug( log.debug(
"Force stop fetching submission events from L1, reached debugForceSyncStopBlockNumber={}", "Force stop fetching submission events from L1, reached debugForceSyncStopBlockNumber={}",
debugForceSyncStopBlockNumber debugForceSyncStopBlockNumber,
) )
return this.stop() return this.stop()
} }
@@ -51,7 +51,7 @@ internal class SubmissionEventsFetchingTask(
// Queue is full, no need to fetch more // Queue is full, no need to fetch more
log.debug( log.debug(
"skipping fetching submission events from L1, internal queue is full size={}", "skipping fetching submission events from L1, internal queue is full size={}",
submissionEventsQueue.size submissionEventsQueue.size,
) )
return SafeFuture.completedFuture(Unit) return SafeFuture.completedFuture(Unit)
} }
@@ -74,21 +74,21 @@ internal class SubmissionEventsFetchingTask(
return if (latestFetchedFinalization.get() != null) { return if (latestFetchedFinalization.get() != null) {
log.trace( log.trace(
"fetching submission events from L1 startBlockNumber={}", "fetching submission events from L1 startBlockNumber={}",
latestFetchedFinalization.get().event.endBlockNumber + 1u latestFetchedFinalization.get().event.endBlockNumber + 1u,
) )
submissionEventsClient.findFinalizationAndDataSubmissionV3Events( submissionEventsClient.findFinalizationAndDataSubmissionV3Events(
fromL1BlockNumber = latestFetchedFinalization.get().log.blockNumber.toBlockParameter(), fromL1BlockNumber = latestFetchedFinalization.get().log.blockNumber.toBlockParameter(),
finalizationStartBlockNumber = latestFetchedFinalization.get().event.endBlockNumber + 1u finalizationStartBlockNumber = latestFetchedFinalization.get().event.endBlockNumber + 1u,
) )
} else { } else {
log.trace( log.trace(
"fetching submission events from L1 startBlockNumber={}", "fetching submission events from L1 startBlockNumber={}",
l2StartBlockNumber l2StartBlockNumber,
) )
submissionEventsClient submissionEventsClient
.findFinalizationAndDataSubmissionV3EventsContainingL2BlockNumber( .findFinalizationAndDataSubmissionV3EventsContainingL2BlockNumber(
fromL1BlockNumber = l1EarliestBlockWithFinalizationThatSupportRecovery, fromL1BlockNumber = l1EarliestBlockWithFinalizationThatSupportRecovery,
l2BlockNumber = l2StartBlockNumber l2BlockNumber = l2StartBlockNumber,
) )
} }
} }

View File

@@ -28,7 +28,7 @@ import kotlin.time.Duration.Companion.seconds
*/ */
data class SubmissionEventsAndData<T>( data class SubmissionEventsAndData<T>(
val submissionEvents: FinalizationAndDataEventsV3, val submissionEvents: FinalizationAndDataEventsV3,
val data: List<T> val data: List<T>,
) )
class SubmissionsFetchingTask( class SubmissionsFetchingTask(
@@ -44,11 +44,11 @@ class SubmissionsFetchingTask(
private val compressedBlobsQueueLimit: Int, private val compressedBlobsQueueLimit: Int,
private val targetDecompressedBlobsQueueLimit: Int, private val targetDecompressedBlobsQueueLimit: Int,
private val debugForceSyncStopBlockNumber: ULong?, private val debugForceSyncStopBlockNumber: ULong?,
private val log: Logger = LogManager.getLogger(SubmissionsFetchingTask::class.java) private val log: Logger = LogManager.getLogger(SubmissionsFetchingTask::class.java),
) : PeriodicPollingService( ) : PeriodicPollingService(
vertx = vertx, vertx = vertx,
pollingIntervalMs = l1PollingInterval.inWholeMilliseconds, pollingIntervalMs = l1PollingInterval.inWholeMilliseconds,
log = log log = log,
) { ) {
init { init {
require(submissionEventsQueueLimit >= 1) { require(submissionEventsQueueLimit >= 1) {
@@ -84,7 +84,7 @@ class SubmissionsFetchingTask(
l2StartBlockNumber = l2StartBlockNumberToFetchInclusive, l2StartBlockNumber = l2StartBlockNumberToFetchInclusive,
submissionEventsQueue = submissionEventsQueue, submissionEventsQueue = submissionEventsQueue,
queueLimit = submissionEventsQueueLimit, queueLimit = submissionEventsQueueLimit,
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber,
) )
private val blobFetchingTask = BlobsFetchingTask( private val blobFetchingTask = BlobsFetchingTask(
vertx = vertx, vertx = vertx,
@@ -93,7 +93,7 @@ class SubmissionsFetchingTask(
blobsFetcher = blobsFetcher, blobsFetcher = blobsFetcher,
transactionDetailsClient = transactionDetailsClient, transactionDetailsClient = transactionDetailsClient,
compressedBlobsQueue = compressedBlobsQueue, compressedBlobsQueue = compressedBlobsQueue,
compressedBlobsQueueLimit = compressedBlobsQueueLimit compressedBlobsQueueLimit = compressedBlobsQueueLimit,
) )
private val blobDecompressionTask = BlobDecompressionTask( private val blobDecompressionTask = BlobDecompressionTask(
vertx = vertx, vertx = vertx,
@@ -101,7 +101,7 @@ class SubmissionsFetchingTask(
blobDecompressor = blobDecompressor, blobDecompressor = blobDecompressor,
rawBlobsQueue = compressedBlobsQueue, rawBlobsQueue = compressedBlobsQueue,
decompressedBlocksQueue = decompressedBlocksQueue, decompressedBlocksQueue = decompressedBlocksQueue,
decompressedFinalizationQueueLimit = dynamicDecompressedBlobsQueueLimit::get decompressedFinalizationQueueLimit = dynamicDecompressedBlobsQueueLimit::get,
) )
@Synchronized @Synchronized
@@ -109,7 +109,7 @@ class SubmissionsFetchingTask(
return SafeFuture.allOf( return SafeFuture.allOf(
submissionEventsFetchingTask.start(), submissionEventsFetchingTask.start(),
blobFetchingTask.start(), blobFetchingTask.start(),
blobDecompressionTask.start() blobDecompressionTask.start(),
).thenCompose { super.start() } ).thenCompose { super.start() }
} }
@@ -118,7 +118,7 @@ class SubmissionsFetchingTask(
return SafeFuture.allOf( return SafeFuture.allOf(
submissionEventsFetchingTask.stop(), submissionEventsFetchingTask.stop(),
blobFetchingTask.stop(), blobFetchingTask.stop(),
blobDecompressionTask.stop() blobDecompressionTask.stop(),
).thenCompose { super.stop() } ).thenCompose { super.stop() }
} }
@@ -136,7 +136,7 @@ class SubmissionsFetchingTask(
@Synchronized @Synchronized
fun pruneQueueForElementsUpToInclusive( fun pruneQueueForElementsUpToInclusive(
elHeadBlockNumber: ULong elHeadBlockNumber: ULong,
) { ) {
decompressedBlocksQueue.removeIf { decompressedBlocksQueue.removeIf {
it.submissionEvents.dataFinalizedEvent.event.endBlockNumber <= elHeadBlockNumber it.submissionEvents.dataFinalizedEvent.event.endBlockNumber <= elHeadBlockNumber

View File

@@ -29,7 +29,7 @@ class BlobDecompressorAndDeserializerV1Test {
private val blockStaticFields = BlockHeaderStaticFields( private val blockStaticFields = BlockHeaderStaticFields(
coinbase = Address.ZERO.toArray(), coinbase = Address.ZERO.toArray(),
gasLimit = 30_000_000UL, gasLimit = 30_000_000UL,
difficulty = 0UL difficulty = 0UL,
) )
private lateinit var decompressorToDomain: BlobDecompressorAndDeserializer private lateinit var decompressorToDomain: BlobDecompressorAndDeserializer
private lateinit var vertx: Vertx private lateinit var vertx: Vertx
@@ -39,7 +39,7 @@ class BlobDecompressorAndDeserializerV1Test {
vertx = Vertx.vertx() vertx = Vertx.vertx()
compressor = GoBackedBlobCompressor.getInstance( compressor = GoBackedBlobCompressor.getInstance(
compressorVersion = BlobCompressorVersion.V1_2, compressorVersion = BlobCompressorVersion.V1_2,
dataLimit = 124 * 1024 dataLimit = 124 * 1024,
) )
val decompressor = GoNativeBlobDecompressorFactory.getInstance(BlobDecompressorVersion.V1_2_0) val decompressor = GoNativeBlobDecompressorFactory.getInstance(BlobDecompressorVersion.V1_2_0)
decompressorToDomain = BlobDecompressorToDomainV1(decompressor, blockStaticFields, vertx) decompressorToDomain = BlobDecompressorToDomainV1(decompressor, blockStaticFields, vertx)
@@ -57,7 +57,7 @@ class BlobDecompressorAndDeserializerV1Test {
} }
private fun assertBlockCompressionAndDecompression( private fun assertBlockCompressionAndDecompression(
blocksRLP: List<ByteArray> blocksRLP: List<ByteArray>,
) { ) {
val blocks = blocksRLP.map(RLP::decodeBlockWithMainnetFunctions) val blocks = blocksRLP.map(RLP::decodeBlockWithMainnetFunctions)
val startingBlockNumber = blocks[0].header.number.toULong() val startingBlockNumber = blocks[0].header.number.toULong()
@@ -66,7 +66,7 @@ class BlobDecompressorAndDeserializerV1Test {
val recoveredBlocks = decompressorToDomain.decompress( val recoveredBlocks = decompressorToDomain.decompress(
startBlockNumber = startingBlockNumber, startBlockNumber = startingBlockNumber,
blobs = blobs blobs = blobs,
).get() ).get()
assertThat(recoveredBlocks[0].header.blockNumber).isEqualTo(startingBlockNumber) assertThat(recoveredBlocks[0].header.blockNumber).isEqualTo(startingBlockNumber)
@@ -77,7 +77,7 @@ class BlobDecompressorAndDeserializerV1Test {
private fun assertBlockData( private fun assertBlockData(
uncompressed: BlockFromL1RecoveredData, uncompressed: BlockFromL1RecoveredData,
original: Block original: Block,
) { ) {
try { try {
assertThat(uncompressed.header.blockNumber).isEqualTo(original.header.number.toULong()) assertThat(uncompressed.header.blockNumber).isEqualTo(original.header.number.toULong())
@@ -94,14 +94,14 @@ class BlobDecompressorAndDeserializerV1Test {
"uncompressed block does not match expected original: blockNumber: ${e.message} " + "uncompressed block does not match expected original: blockNumber: ${e.message} " +
"\n original =$original " + "\n original =$original " +
"\n uncompressed=$uncompressed ", "\n uncompressed=$uncompressed ",
e e,
) )
} }
} }
private fun assertTransactionData( private fun assertTransactionData(
uncompressed: TransactionFromL1RecoveredData, uncompressed: TransactionFromL1RecoveredData,
original: Transaction original: Transaction,
) { ) {
assertThat(uncompressed.type).isEqualTo(original.type.serializedType.toUByte()) assertThat(uncompressed.type).isEqualTo(original.type.serializedType.toUByte())
assertThat(uncompressed.from).isEqualTo(original.sender.toArray()) assertThat(uncompressed.from).isEqualTo(original.sender.toArray())

View File

@@ -13,7 +13,7 @@ class StartingBlockCalculatorTest {
lookbackFetchingIntervals( lookbackFetchingIntervals(
headBlockNumber = 50UL, headBlockNumber = 50UL,
recoveryStartBlockNumber = null, recoveryStartBlockNumber = null,
lookbackWindow = 10UL lookbackWindow = 10UL,
).also { intervals -> ).also { intervals ->
assertThat(intervals.l1Interval).isNull() assertThat(intervals.l1Interval).isNull()
assertThat(intervals.elInterval).isEqualTo(BlockInterval(41UL, 50UL)) assertThat(intervals.elInterval).isEqualTo(BlockInterval(41UL, 50UL))
@@ -23,7 +23,7 @@ class StartingBlockCalculatorTest {
lookbackFetchingIntervals( lookbackFetchingIntervals(
headBlockNumber = 5UL, headBlockNumber = 5UL,
recoveryStartBlockNumber = null, recoveryStartBlockNumber = null,
lookbackWindow = 10UL lookbackWindow = 10UL,
).also { intervals -> ).also { intervals ->
assertThat(intervals.l1Interval).isNull() assertThat(intervals.l1Interval).isNull()
assertThat(intervals.elInterval).isEqualTo(BlockInterval(0UL, 5UL)) assertThat(intervals.elInterval).isEqualTo(BlockInterval(0UL, 5UL))
@@ -35,7 +35,7 @@ class StartingBlockCalculatorTest {
lookbackFetchingIntervals( lookbackFetchingIntervals(
headBlockNumber = 50UL, headBlockNumber = 50UL,
recoveryStartBlockNumber = 51UL, recoveryStartBlockNumber = 51UL,
lookbackWindow = 10UL lookbackWindow = 10UL,
).also { intervals -> ).also { intervals ->
assertThat(intervals.l1Interval).isNull() assertThat(intervals.l1Interval).isNull()
assertThat(intervals.elInterval).isEqualTo(BlockInterval(41UL, 50UL)) assertThat(intervals.elInterval).isEqualTo(BlockInterval(41UL, 50UL))
@@ -47,7 +47,7 @@ class StartingBlockCalculatorTest {
lookbackFetchingIntervals( lookbackFetchingIntervals(
headBlockNumber = 0UL, headBlockNumber = 0UL,
recoveryStartBlockNumber = 1UL, recoveryStartBlockNumber = 1UL,
lookbackWindow = 10UL lookbackWindow = 10UL,
).also { intervals -> ).also { intervals ->
assertThat(intervals.l1Interval).isNull() assertThat(intervals.l1Interval).isNull()
assertThat(intervals.elInterval).isEqualTo(BlockInterval(0UL, 0UL)) assertThat(intervals.elInterval).isEqualTo(BlockInterval(0UL, 0UL))
@@ -59,7 +59,7 @@ class StartingBlockCalculatorTest {
lookbackFetchingIntervals( lookbackFetchingIntervals(
headBlockNumber = 50UL, headBlockNumber = 50UL,
recoveryStartBlockNumber = 10UL, recoveryStartBlockNumber = 10UL,
lookbackWindow = 10UL lookbackWindow = 10UL,
).also { intervals -> ).also { intervals ->
assertThat(intervals.l1Interval).isEqualTo(BlockInterval(41UL, 50UL)) assertThat(intervals.l1Interval).isEqualTo(BlockInterval(41UL, 50UL))
assertThat(intervals.elInterval).isNull() assertThat(intervals.elInterval).isNull()
@@ -71,7 +71,7 @@ class StartingBlockCalculatorTest {
lookbackFetchingIntervals( lookbackFetchingIntervals(
headBlockNumber = 50UL, headBlockNumber = 50UL,
recoveryStartBlockNumber = 45UL, recoveryStartBlockNumber = 45UL,
lookbackWindow = 10UL lookbackWindow = 10UL,
).also { intervals -> ).also { intervals ->
assertThat(intervals.l1Interval).isEqualTo(BlockInterval(45UL, 50UL)) assertThat(intervals.l1Interval).isEqualTo(BlockInterval(45UL, 50UL))
assertThat(intervals.elInterval).isEqualTo(BlockInterval(41UL, 44UL)) assertThat(intervals.elInterval).isEqualTo(BlockInterval(41UL, 44UL))
@@ -86,7 +86,7 @@ class StartingBlockCalculatorTest {
startBlockToFetchFromL1( startBlockToFetchFromL1(
headBlockNumber = 500UL, headBlockNumber = 500UL,
recoveryStartBlockNumber = null, recoveryStartBlockNumber = null,
lookbackWindow = 256UL lookbackWindow = 256UL,
).also { result -> ).also { result ->
// Then // Then
assertThat(result).isEqualTo(501UL) assertThat(result).isEqualTo(501UL)
@@ -95,7 +95,7 @@ class StartingBlockCalculatorTest {
startBlockToFetchFromL1( startBlockToFetchFromL1(
headBlockNumber = 200UL, headBlockNumber = 200UL,
recoveryStartBlockNumber = null, recoveryStartBlockNumber = null,
lookbackWindow = 256UL lookbackWindow = 256UL,
).also { result -> ).also { result ->
// Then // Then
assertThat(result).isEqualTo(201UL) assertThat(result).isEqualTo(201UL)
@@ -107,7 +107,7 @@ class StartingBlockCalculatorTest {
startBlockToFetchFromL1( startBlockToFetchFromL1(
headBlockNumber = 500UL, headBlockNumber = 500UL,
recoveryStartBlockNumber = 250UL, recoveryStartBlockNumber = 250UL,
lookbackWindow = 100UL lookbackWindow = 100UL,
).also { result -> ).also { result ->
// Then // Then
assertThat(result).isEqualTo(400UL) assertThat(result).isEqualTo(400UL)
@@ -119,7 +119,7 @@ class StartingBlockCalculatorTest {
startBlockToFetchFromL1( startBlockToFetchFromL1(
headBlockNumber = 500UL, headBlockNumber = 500UL,
recoveryStartBlockNumber = 450UL, recoveryStartBlockNumber = 450UL,
lookbackWindow = 100UL lookbackWindow = 100UL,
).also { result -> ).also { result ->
// Then // Then
assertThat(result).isEqualTo(450UL) assertThat(result).isEqualTo(450UL)
@@ -129,7 +129,7 @@ class StartingBlockCalculatorTest {
startBlockToFetchFromL1( startBlockToFetchFromL1(
headBlockNumber = 50UL, headBlockNumber = 50UL,
recoveryStartBlockNumber = 45UL, recoveryStartBlockNumber = 45UL,
lookbackWindow = 100UL lookbackWindow = 100UL,
).also { result -> ).also { result ->
// Then // Then
assertThat(result).isEqualTo(45UL) assertThat(result).isEqualTo(45UL)

View File

@@ -21,7 +21,7 @@ class ExecutionLayerInProcessClient(
private val blockchainService: BlockchainService, private val blockchainService: BlockchainService,
private val stateRecoveryModeManager: RecoveryModeManager, private val stateRecoveryModeManager: RecoveryModeManager,
private val stateRecoveryStatusPersistence: RecoveryStatusPersistence, private val stateRecoveryStatusPersistence: RecoveryStatusPersistence,
private val blockImporter: BlockImporter private val blockImporter: BlockImporter,
) : ExecutionLayerClient { ) : ExecutionLayerClient {
companion object { companion object {
fun create( fun create(
@@ -29,7 +29,7 @@ class ExecutionLayerInProcessClient(
simulatorService: BlockSimulationService, simulatorService: BlockSimulationService,
synchronizationService: SynchronizationService, synchronizationService: SynchronizationService,
stateRecoveryModeManager: RecoveryModeManager, stateRecoveryModeManager: RecoveryModeManager,
stateRecoveryStatusPersistence: RecoveryStatusPersistence stateRecoveryStatusPersistence: RecoveryStatusPersistence,
): ExecutionLayerInProcessClient { ): ExecutionLayerInProcessClient {
return ExecutionLayerInProcessClient( return ExecutionLayerInProcessClient(
blockchainService = blockchainService, blockchainService = blockchainService,
@@ -38,8 +38,8 @@ class ExecutionLayerInProcessClient(
blockImporter = BlockImporter( blockImporter = BlockImporter(
blockchainService = blockchainService, blockchainService = blockchainService,
simulatorService = simulatorService, simulatorService = simulatorService,
synchronizationService = synchronizationService synchronizationService = synchronizationService,
) ),
) )
} }
} }
@@ -71,8 +71,8 @@ class ExecutionLayerInProcessClient(
SafeFuture.completedFuture( SafeFuture.completedFuture(
BlockNumberAndHash( BlockNumberAndHash(
it.number.toULong(), it.number.toULong(),
it.blockHash.toArray() it.blockHash.toArray(),
) ),
) )
} }
?: SafeFuture.failedFuture(IllegalArgumentException("Block not found for parameter: $blockParameter")) ?: SafeFuture.failedFuture(IllegalArgumentException("Block not found for parameter: $blockParameter"))
@@ -91,8 +91,8 @@ class ExecutionLayerInProcessClient(
.completedFuture( .completedFuture(
StateRecoveryStatus( StateRecoveryStatus(
headBlockNumber = stateRecoveryModeManager.headBlockNumber, headBlockNumber = stateRecoveryModeManager.headBlockNumber,
stateRecoverStartBlockNumber = stateRecoveryModeManager.targetBlockNumber stateRecoverStartBlockNumber = stateRecoveryModeManager.targetBlockNumber,
) ),
) )
} }
@@ -102,8 +102,8 @@ class ExecutionLayerInProcessClient(
return SafeFuture.completedFuture( return SafeFuture.completedFuture(
StateRecoveryStatus( StateRecoveryStatus(
headBlockNumber = stateRecoveryModeManager.headBlockNumber, headBlockNumber = stateRecoveryModeManager.headBlockNumber,
stateRecoverStartBlockNumber = stateRecoveryStatusPersistence.getRecoveryStartBlockNumber() stateRecoverStartBlockNumber = stateRecoveryStatusPersistence.getRecoveryStartBlockNumber(),
) ),
) )
} }
@@ -113,7 +113,7 @@ class ExecutionLayerInProcessClient(
} else { } else {
log.debug( log.debug(
"importing blocks from blob: blocks={}", "importing blocks from blob: blocks={}",
CommonDomainFunctions.blockIntervalString(blocks.first().header.blockNumber, blocks.last().header.blockNumber) CommonDomainFunctions.blockIntervalString(blocks.first().header.blockNumber, blocks.last().header.blockNumber),
) )
} }
} }

View File

@@ -37,7 +37,7 @@ fun createAppAllInProcess(
blobScanRequestRetryConfig: RetryConfig, blobScanRequestRetryConfig: RetryConfig,
blobscanRequestRatelimitBackoffDelay: Duration?, blobscanRequestRatelimitBackoffDelay: Duration?,
blockHeaderStaticFields: BlockHeaderStaticFields, blockHeaderStaticFields: BlockHeaderStaticFields,
appConfig: StateRecoveryApp.Config appConfig: StateRecoveryApp.Config,
): StateRecoveryApp { ): StateRecoveryApp {
return createAppClients( return createAppClients(
vertx = vertx, vertx = vertx,
@@ -49,7 +49,7 @@ fun createAppAllInProcess(
l1RequestRetryConfig = l1RequestRetryConfig, l1RequestRetryConfig = l1RequestRetryConfig,
blobScanEndpoint = blobScanEndpoint, blobScanEndpoint = blobScanEndpoint,
blobScanRequestRetryConfig = blobScanRequestRetryConfig, blobScanRequestRetryConfig = blobScanRequestRetryConfig,
blobscanRequestRateLimitBackoffDelay = blobscanRequestRatelimitBackoffDelay blobscanRequestRateLimitBackoffDelay = blobscanRequestRatelimitBackoffDelay,
).let { clients -> ).let { clients ->
val app = StateRecoveryApp( val app = StateRecoveryApp(
vertx = vertx, vertx = vertx,
@@ -60,7 +60,7 @@ fun createAppAllInProcess(
stateManagerClient = clients.stateManagerClient, stateManagerClient = clients.stateManagerClient,
transactionDetailsClient = clients.transactionDetailsClient, transactionDetailsClient = clients.transactionDetailsClient,
blockHeaderStaticFields = blockHeaderStaticFields, blockHeaderStaticFields = blockHeaderStaticFields,
config = appConfig config = appConfig,
) )
app app
} }
@@ -71,7 +71,7 @@ data class AppClients(
val ethLogsSearcher: EthLogsSearcherImpl, val ethLogsSearcher: EthLogsSearcherImpl,
val blobScanClient: BlobScanClient, val blobScanClient: BlobScanClient,
val stateManagerClient: StateManagerClientV1, val stateManagerClient: StateManagerClientV1,
val transactionDetailsClient: TransactionDetailsClient val transactionDetailsClient: TransactionDetailsClient,
) )
fun RetryConfig.toRequestRetryConfig(): RequestRetryConfig { fun RetryConfig.toRequestRetryConfig(): RequestRetryConfig {
@@ -79,7 +79,7 @@ fun RetryConfig.toRequestRetryConfig(): RequestRetryConfig {
maxRetries = this.maxRetries, maxRetries = this.maxRetries,
timeout = this.timeout, timeout = this.timeout,
backoffDelay = this.backoffDelay, backoffDelay = this.backoffDelay,
failuresWarningThreshold = this.failuresWarningThreshold failuresWarningThreshold = this.failuresWarningThreshold,
) )
} }
@@ -95,14 +95,14 @@ fun createAppClients(
stateManagerClientEndpoint: URI, stateManagerClientEndpoint: URI,
blobscanRequestRateLimitBackoffDelay: Duration? = null, blobscanRequestRateLimitBackoffDelay: Duration? = null,
stateManagerRequestRetry: RetryConfig = RetryConfig(backoffDelay = 1.seconds), stateManagerRequestRetry: RetryConfig = RetryConfig(backoffDelay = 1.seconds),
zkStateManagerVersion: String = "2.3.0" zkStateManagerVersion: String = "2.3.0",
): AppClients { ): AppClients {
val lineaContractClient = Web3JLineaRollupSmartContractClientReadOnly( val lineaContractClient = Web3JLineaRollupSmartContractClientReadOnly(
contractAddress = smartContractAddress, contractAddress = smartContractAddress,
web3j = createWeb3jHttpClient( web3j = createWeb3jHttpClient(
rpcUrl = l1RpcEndpoint.toString(), rpcUrl = l1RpcEndpoint.toString(),
log = LogManager.getLogger("linea.plugin.staterecovery.clients.l1.smart-contract") log = LogManager.getLogger("linea.plugin.staterecovery.clients.l1.smart-contract"),
) ),
) )
val ethLogsSearcher = run { val ethLogsSearcher = run {
val log = LogManager.getLogger("linea.plugin.staterecovery.clients.l1.logs-searcher") val log = LogManager.getLogger("linea.plugin.staterecovery.clients.l1.logs-searcher")
@@ -110,15 +110,15 @@ fun createAppClients(
vertx = vertx, vertx = vertx,
rpcUrl = l1RpcEndpoint.toString(), rpcUrl = l1RpcEndpoint.toString(),
requestRetryConfig = l1RequestRetryConfig, requestRetryConfig = l1RequestRetryConfig,
log = log log = log,
) )
EthLogsSearcherImpl( EthLogsSearcherImpl(
vertx = vertx, vertx = vertx,
ethApiClient = web3jEthApiClient, ethApiClient = web3jEthApiClient,
config = EthLogsSearcherImpl.Config( config = EthLogsSearcherImpl.Config(
loopSuccessBackoffDelay = l1SuccessBackoffDelay loopSuccessBackoffDelay = l1SuccessBackoffDelay,
), ),
log = log log = log,
) )
} }
val blobScanClient = BlobScanClient.create( val blobScanClient = BlobScanClient.create(
@@ -126,7 +126,7 @@ fun createAppClients(
endpoint = blobScanEndpoint, endpoint = blobScanEndpoint,
requestRetryConfig = blobScanRequestRetryConfig, requestRetryConfig = blobScanRequestRetryConfig,
logger = LogManager.getLogger("linea.plugin.staterecovery.clients.l1.blob-scan"), logger = LogManager.getLogger("linea.plugin.staterecovery.clients.l1.blob-scan"),
rateLimitBackoffDelay = blobscanRequestRateLimitBackoffDelay rateLimitBackoffDelay = blobscanRequestRateLimitBackoffDelay,
) )
val jsonRpcClientFactory = VertxHttpJsonRpcClientFactory(vertx, MicrometerMetricsFacade(meterRegistry)) val jsonRpcClientFactory = VertxHttpJsonRpcClientFactory(vertx, MicrometerMetricsFacade(meterRegistry))
val stateManagerClient: StateManagerClientV1 = StateManagerV1JsonRpcClient.create( val stateManagerClient: StateManagerClientV1 = StateManagerV1JsonRpcClient.create(
@@ -135,19 +135,19 @@ fun createAppClients(
maxInflightRequestsPerClient = 10u, maxInflightRequestsPerClient = 10u,
requestRetry = stateManagerRequestRetry.toRequestRetryConfig(), requestRetry = stateManagerRequestRetry.toRequestRetryConfig(),
zkStateManagerVersion = zkStateManagerVersion, zkStateManagerVersion = zkStateManagerVersion,
logger = LogManager.getLogger("linea.plugin.staterecovery.clients.state-manager") logger = LogManager.getLogger("linea.plugin.staterecovery.clients.state-manager"),
) )
val transactionDetailsClient: TransactionDetailsClient = VertxTransactionDetailsClient.create( val transactionDetailsClient: TransactionDetailsClient = VertxTransactionDetailsClient.create(
jsonRpcClientFactory = jsonRpcClientFactory, jsonRpcClientFactory = jsonRpcClientFactory,
endpoint = l1RpcEndpoint, endpoint = l1RpcEndpoint,
retryConfig = l1RequestRetryConfig.toRequestRetryConfig(), retryConfig = l1RequestRetryConfig.toRequestRetryConfig(),
logger = LogManager.getLogger("linea.plugin.staterecovery.clients.l1.transaction-details") logger = LogManager.getLogger("linea.plugin.staterecovery.clients.l1.transaction-details"),
) )
return AppClients( return AppClients(
lineaContractClient = lineaContractClient, lineaContractClient = lineaContractClient,
ethLogsSearcher = ethLogsSearcher, ethLogsSearcher = ethLogsSearcher,
blobScanClient = blobScanClient, blobScanClient = blobScanClient,
stateManagerClient = stateManagerClient, stateManagerClient = stateManagerClient,
transactionDetailsClient = transactionDetailsClient transactionDetailsClient = transactionDetailsClient,
) )
} }

View File

@@ -6,7 +6,7 @@ import org.hyperledger.besu.plugin.data.BlockHeader
data class BlockContextData( data class BlockContextData(
private val blockHeader: BlockHeader, private val blockHeader: BlockHeader,
private val blockBody: BlockBody private val blockBody: BlockBody,
) : BlockContext { ) : BlockContext {
override fun getBlockHeader(): BlockHeader = blockHeader override fun getBlockHeader(): BlockHeader = blockHeader
override fun getBlockBody(): BlockBody = blockBody override fun getBlockBody(): BlockBody = blockBody

View File

@@ -13,7 +13,7 @@ import java.util.concurrent.ConcurrentHashMap
class BlockHashLookupWithRecoverySupport( class BlockHashLookupWithRecoverySupport(
val lookbackWindow: ULong, val lookbackWindow: ULong,
private val log: Logger = LogManager.getLogger(BlockHashLookupWithRecoverySupport::class.java) private val log: Logger = LogManager.getLogger(BlockHashLookupWithRecoverySupport::class.java),
) : BlockHashLookup { ) : BlockHashLookup {
private val lookbackHashesMap = ConcurrentHashMap<ULong, ByteArray>() private val lookbackHashesMap = ConcurrentHashMap<ULong, ByteArray>()

View File

@@ -22,8 +22,8 @@ class BlockImporter(
private val simulatorService: BlockSimulationService, private val simulatorService: BlockSimulationService,
private val synchronizationService: SynchronizationService, private val synchronizationService: SynchronizationService,
private val blockHashLookup: BlockHashLookupWithRecoverySupport = BlockHashLookupWithRecoverySupport( private val blockHashLookup: BlockHashLookupWithRecoverySupport = BlockHashLookupWithRecoverySupport(
lookbackWindow = 256UL lookbackWindow = 256UL,
) ),
) { ) {
private val log = LogManager.getLogger(BlockImporter::class.java) private val log = LogManager.getLogger(BlockImporter::class.java)
private val chainId = blockchainService.chainId.orElseThrow().toULong() private val chainId = blockchainService.chainId.orElseThrow().toULong()
@@ -40,16 +40,16 @@ class BlockImporter(
} }
private fun executeBlockWithTransactionsWithoutSignature( private fun executeBlockWithTransactionsWithoutSignature(
block: BlockFromL1RecoveredData block: BlockFromL1RecoveredData,
): PluginBlockSimulationResult { ): PluginBlockSimulationResult {
log.trace( log.trace(
"simulating import block={} blockHash={}", "simulating import block={} blockHash={}",
block.header.blockNumber, block.header.blockNumber,
block.header.blockHash.encodeHex() block.header.blockHash.encodeHex(),
) )
val transactions = TransactionMapper.mapToBesu( val transactions = TransactionMapper.mapToBesu(
block.transactions, block.transactions,
chainId chainId,
) )
val parentBlockNumber = block.header.blockNumber.toLong() - 1 val parentBlockNumber = block.header.blockNumber.toLong() - 1
@@ -58,13 +58,13 @@ class BlockImporter(
parentBlockNumber, parentBlockNumber,
transactions, transactions,
createOverrides(block, blockHashLookup::getHash), createOverrides(block, blockHashLookup::getHash),
StateOverrideMap() StateOverrideMap(),
) )
log.trace( log.trace(
" import simulation result: block={} blockHeader={}", " import simulation result: block={} blockHeader={}",
executedBlockResult.blockHeader.number, executedBlockResult.blockHeader.number,
executedBlockResult.blockHeader executedBlockResult.blockHeader,
) )
return executedBlockResult return executedBlockResult
} }
@@ -73,7 +73,7 @@ class BlockImporter(
log.trace( log.trace(
"calling simulateAndPersistWorldState block={} blockHeader={}", "calling simulateAndPersistWorldState block={} blockHeader={}",
context.blockHeader.number, context.blockHeader.number,
context.blockHeader context.blockHeader,
) )
val parentBlockNumber = context.blockHeader.number - 1 val parentBlockNumber = context.blockHeader.number - 1
val importedBlockResult = val importedBlockResult =
@@ -81,12 +81,12 @@ class BlockImporter(
parentBlockNumber, parentBlockNumber,
context.blockBody.transactions, context.blockBody.transactions,
createOverrides(context.blockHeader, blockHashLookup::getHash), createOverrides(context.blockHeader, blockHashLookup::getHash),
StateOverrideMap() StateOverrideMap(),
) )
log.trace( log.trace(
"simulateAndPersistWorldState result: block={} blockHeader={}", "simulateAndPersistWorldState result: block={} blockHeader={}",
context.blockHeader.number, context.blockHeader.number,
importedBlockResult.blockHeader importedBlockResult.blockHeader,
) )
storeAndSetHead(importedBlockResult) storeAndSetHead(importedBlockResult)
return importedBlockResult return importedBlockResult
@@ -95,12 +95,12 @@ class BlockImporter(
private fun storeAndSetHead(block: PluginBlockSimulationResult) { private fun storeAndSetHead(block: PluginBlockSimulationResult) {
log.debug( log.debug(
"storeAndSetHead result: blockHeader={}", "storeAndSetHead result: blockHeader={}",
block.blockHeader block.blockHeader,
) )
blockchainService.storeBlock( blockchainService.storeBlock(
block.blockHeader, block.blockHeader,
block.blockBody, block.blockBody,
block.receipts block.receipts,
) )
synchronizationService.setHeadUnsafe(block.blockHeader, block.blockBody) synchronizationService.setHeadUnsafe(block.blockHeader, block.blockBody)
} }
@@ -108,7 +108,7 @@ class BlockImporter(
companion object { companion object {
fun createOverrides( fun createOverrides(
blockFromBlob: BlockFromL1RecoveredData, blockFromBlob: BlockFromL1RecoveredData,
blockHashLookup: (Long) -> Hash blockHashLookup: (Long) -> Hash,
): BlockOverrides { ): BlockOverrides {
return BlockOverrides.builder() return BlockOverrides.builder()
.blockHash(Hash.wrap(Bytes32.wrap(blockFromBlob.header.blockHash))) .blockHash(Hash.wrap(Bytes32.wrap(blockFromBlob.header.blockHash)))
@@ -124,7 +124,7 @@ class BlockImporter(
fun createOverrides( fun createOverrides(
blockHeader: BlockHeader, blockHeader: BlockHeader,
blockHashLookup: (Long) -> Hash blockHashLookup: (Long) -> Hash,
): BlockOverrides { ): BlockOverrides {
return BlockOverrides.builder() return BlockOverrides.builder()
.feeRecipient(blockHeader.coinbase) .feeRecipient(blockHeader.coinbase)

View File

@@ -36,7 +36,7 @@ open class LineaStateRecoveryPlugin : BesuPlugin {
warningExceptionTime = 5.minutes, warningExceptionTime = 5.minutes,
jvmMetricsEnabled = false, jvmMetricsEnabled = false,
prometheusMetricsEnabled = false, prometheusMetricsEnabled = false,
preferNativeTransport = false preferNativeTransport = false,
) )
private val cliOptions = PluginCliOptions() private val cliOptions = PluginCliOptions()
private lateinit var serviceManager: ServiceManager private lateinit var serviceManager: ServiceManager
@@ -59,18 +59,18 @@ open class LineaStateRecoveryPlugin : BesuPlugin {
val blockHeaderStaticFields = BlockHeaderStaticFields( val blockHeaderStaticFields = BlockHeaderStaticFields(
coinbase = config.lineaSequencerBeneficiaryAddress.toArray(), coinbase = config.lineaSequencerBeneficiaryAddress.toArray(),
gasLimit = config.lineaBlockGasLimit, gasLimit = config.lineaBlockGasLimit,
difficulty = config.lineaBlockDifficulty difficulty = config.lineaBlockDifficulty,
) )
this.recoveryStatusPersistence = FileBasedRecoveryStatusPersistence( this.recoveryStatusPersistence = FileBasedRecoveryStatusPersistence(
serviceManager.getServiceOrThrow(BesuConfiguration::class.java) serviceManager.getServiceOrThrow(BesuConfiguration::class.java)
.dataPath .dataPath
.resolve("plugin-staterecovery-status.json") .resolve("plugin-staterecovery-status.json"),
) )
log.info( log.info(
"starting: config={} blockHeaderStaticFields={} previousRecoveryStartBlockNumber={}", "starting: config={} blockHeaderStaticFields={} previousRecoveryStartBlockNumber={}",
config, config,
blockHeaderStaticFields, blockHeaderStaticFields,
this.recoveryStatusPersistence.getRecoveryStartBlockNumber() this.recoveryStatusPersistence.getRecoveryStartBlockNumber(),
) )
val synchronizationService = serviceManager.getServiceOrThrow(SynchronizationService::class.java) val synchronizationService = serviceManager.getServiceOrThrow(SynchronizationService::class.java)
@@ -80,7 +80,7 @@ open class LineaStateRecoveryPlugin : BesuPlugin {
recoveryStatePersistence = this.recoveryStatusPersistence, recoveryStatePersistence = this.recoveryStatusPersistence,
synchronizationService = synchronizationService, synchronizationService = synchronizationService,
headBlockNumber = blockchainService.chainHeadHeader.number.toULong(), headBlockNumber = blockchainService.chainHeadHeader.number.toULong(),
debugForceSyncStopBlockNumber = config.debugForceSyncStopBlockNumber debugForceSyncStopBlockNumber = config.debugForceSyncStopBlockNumber,
) )
val simulatorService = serviceManager.getServiceOrThrow(BlockSimulationService::class.java) val simulatorService = serviceManager.getServiceOrThrow(BlockSimulationService::class.java)
val executionLayerClient = ExecutionLayerInProcessClient.create( val executionLayerClient = ExecutionLayerInProcessClient.create(
@@ -88,7 +88,7 @@ open class LineaStateRecoveryPlugin : BesuPlugin {
stateRecoveryModeManager = this.recoveryModeManager, stateRecoveryModeManager = this.recoveryModeManager,
stateRecoveryStatusPersistence = this.recoveryStatusPersistence, stateRecoveryStatusPersistence = this.recoveryStatusPersistence,
simulatorService = simulatorService, simulatorService = simulatorService,
synchronizationService = synchronizationService synchronizationService = synchronizationService,
) )
this.stateRecoverApp = run { this.stateRecoverApp = run {
@@ -112,8 +112,8 @@ open class LineaStateRecoveryPlugin : BesuPlugin {
l1LatestSearchBlock = config.l1HighestSearchBlock, l1LatestSearchBlock = config.l1HighestSearchBlock,
l1PollingInterval = config.l1PollingInterval, l1PollingInterval = config.l1PollingInterval,
overridingRecoveryStartBlockNumber = config.overridingRecoveryStartBlockNumber, overridingRecoveryStartBlockNumber = config.overridingRecoveryStartBlockNumber,
debugForceSyncStopBlockNumber = config.debugForceSyncStopBlockNumber debugForceSyncStopBlockNumber = config.debugForceSyncStopBlockNumber,
) ),
) )
} }
// add recoverty mode manager as listener to block added events // add recoverty mode manager as listener to block added events
@@ -129,7 +129,7 @@ open class LineaStateRecoveryPlugin : BesuPlugin {
this.recoveryModeManager.enableRecoveryModeIfNecessary() this.recoveryModeManager.enableRecoveryModeIfNecessary()
log.info( log.info(
"started: recoveryStartBlockNumber={}", "started: recoveryStartBlockNumber={}",
this.recoveryStatusPersistence.getRecoveryStartBlockNumber() this.recoveryStatusPersistence.getRecoveryStartBlockNumber(),
) )
this.stateRecoverApp.start().get() this.stateRecoverApp.start().get()
} }

View File

@@ -25,7 +25,7 @@ data class PluginConfig(
val blobscanRequestRatelimitBackoffDelay: kotlin.time.Duration?, val blobscanRequestRatelimitBackoffDelay: kotlin.time.Duration?,
val shomeiEndpoint: URI, val shomeiEndpoint: URI,
val overridingRecoveryStartBlockNumber: ULong? = null, val overridingRecoveryStartBlockNumber: ULong? = null,
val debugForceSyncStopBlockNumber: ULong? = null val debugForceSyncStopBlockNumber: ULong? = null,
) { ) {
init { init {
require(l1PollingInterval >= 1.milliseconds) { "Polling interval=$l1PollingInterval must be greater than 1ms." } require(l1PollingInterval >= 1.milliseconds) { "Polling interval=$l1PollingInterval must be greater than 1ms." }
@@ -43,7 +43,7 @@ class PluginCliOptions {
description = ["Linea sequencer beneficiary address"], description = ["Linea sequencer beneficiary address"],
required = true, required = true,
converter = [AddressConverter::class], converter = [AddressConverter::class],
defaultValue = "\${env:LINEA_SEQUENCER_BENEFICIARY_ADDRESS}" defaultValue = "\${env:LINEA_SEQUENCER_BENEFICIARY_ADDRESS}",
) )
lateinit var lineaSequencerBeneficiaryAddress: Address lateinit var lineaSequencerBeneficiaryAddress: Address
@@ -51,7 +51,7 @@ class PluginCliOptions {
names = ["--$cliOptionsPrefix-linea-block-gas-limit"], names = ["--$cliOptionsPrefix-linea-block-gas-limit"],
description = ["Linea Block gas limit. Default 2B (2_000_000_000)"], description = ["Linea Block gas limit. Default 2B (2_000_000_000)"],
required = false, required = false,
defaultValue = "\${env:LINEA_BLOCK_GAS_LIMIT}" defaultValue = "\${env:LINEA_BLOCK_GAS_LIMIT}",
) )
var lineaBlockGasLimit: Long = 2_000_000_000L var lineaBlockGasLimit: Long = 2_000_000_000L
@@ -59,7 +59,7 @@ class PluginCliOptions {
names = ["--$cliOptionsPrefix-linea-block-difficulty"], names = ["--$cliOptionsPrefix-linea-block-difficulty"],
description = ["Linea Block difficulty. Default 2"], description = ["Linea Block difficulty. Default 2"],
required = false, required = false,
defaultValue = "\${env:LINEA_BLOCK_DIFFICULTY}" defaultValue = "\${env:LINEA_BLOCK_DIFFICULTY}",
) )
var lineaBlockDifficulty: Long = 2 var lineaBlockDifficulty: Long = 2
@@ -68,14 +68,14 @@ class PluginCliOptions {
description = ["L1 smart contract address"], description = ["L1 smart contract address"],
required = true, required = true,
converter = [AddressConverter::class], converter = [AddressConverter::class],
defaultValue = "\${env:L1_ROLLUP_CONTRACT_ADDRESS}" defaultValue = "\${env:L1_ROLLUP_CONTRACT_ADDRESS}",
) )
lateinit var l1SmartContractAddress: Address lateinit var l1SmartContractAddress: Address
@CommandLine.Option( @CommandLine.Option(
names = ["--$cliOptionsPrefix-l1-endpoint"], names = ["--$cliOptionsPrefix-l1-endpoint"],
description = ["L1 RPC endpoint"], description = ["L1 RPC endpoint"],
required = true required = true,
) )
lateinit var l1RpcEndpoint: URI lateinit var l1RpcEndpoint: URI
@@ -83,7 +83,7 @@ class PluginCliOptions {
names = ["--$cliOptionsPrefix-l1-polling-interval"], names = ["--$cliOptionsPrefix-l1-polling-interval"],
defaultValue = "PT12S", defaultValue = "PT12S",
description = ["L1 polling interval for new finalized blobs"], description = ["L1 polling interval for new finalized blobs"],
required = false required = false,
) )
var l1PollingInterval: java.time.Duration = java.time.Duration.ofSeconds(12) var l1PollingInterval: java.time.Duration = java.time.Duration.ofSeconds(12)
@@ -91,7 +91,7 @@ class PluginCliOptions {
names = ["--$cliOptionsPrefix-l1-get-logs-chunk-size"], names = ["--$cliOptionsPrefix-l1-get-logs-chunk-size"],
defaultValue = "10000", defaultValue = "10000",
description = ["Chuck size (fromBlock..toBlock) for eth_getLogs initial search loop"], description = ["Chuck size (fromBlock..toBlock) for eth_getLogs initial search loop"],
required = false required = false,
) )
var l1GetLogsChunkSize: Int = 10_000 var l1GetLogsChunkSize: Int = 10_000
@@ -100,10 +100,10 @@ class PluginCliOptions {
defaultValue = "EARLIEST", defaultValue = "EARLIEST",
description = [ description = [
"Earliest L1 Block to search for new finalizations on startup.", "Earliest L1 Block to search for new finalizations on startup.",
"Optional, if defined it shall match L1 block with 1st finalization that supports recovery." "Optional, if defined it shall match L1 block with 1st finalization that supports recovery.",
], ],
converter = [BlockParameterConverter::class], converter = [BlockParameterConverter::class],
required = false required = false,
) )
var l1EarliestSearchBlock: BlockParameter = BlockParameter.Tag.EARLIEST var l1EarliestSearchBlock: BlockParameter = BlockParameter.Tag.EARLIEST
@@ -112,10 +112,10 @@ class PluginCliOptions {
defaultValue = "FINALIZED", defaultValue = "FINALIZED",
description = [ description = [
"Highest L1 Block to search for new finalizations.", "Highest L1 Block to search for new finalizations.",
"Finalized is highly recommended, otherwise if state is reverted it may require a full resync. " "Finalized is highly recommended, otherwise if state is reverted it may require a full resync. ",
], ],
converter = [BlockParameterConverter::class], converter = [BlockParameterConverter::class],
required = false required = false,
) )
var l1HighestSearchBlock: BlockParameter = BlockParameter.Tag.FINALIZED var l1HighestSearchBlock: BlockParameter = BlockParameter.Tag.FINALIZED
@@ -123,9 +123,9 @@ class PluginCliOptions {
names = ["--$cliOptionsPrefix-l1-success-backoff-delay"], names = ["--$cliOptionsPrefix-l1-success-backoff-delay"],
description = [ description = [
"L1 RPC api retry backoff delay, default none. ", "L1 RPC api retry backoff delay, default none. ",
"Request will fire as soon as previous response is received" "Request will fire as soon as previous response is received",
], ],
required = false required = false,
) )
var l1RequestSuccessBackoffDelay: java.time.Duration? = null var l1RequestSuccessBackoffDelay: java.time.Duration? = null
@@ -133,7 +133,7 @@ class PluginCliOptions {
names = ["--$cliOptionsPrefix-l1-retry-backoff-delay"], names = ["--$cliOptionsPrefix-l1-retry-backoff-delay"],
defaultValue = "PT1S", defaultValue = "PT1S",
description = ["L1 RPC api retry backoff delay, default 1s"], description = ["L1 RPC api retry backoff delay, default 1s"],
required = false required = false,
) )
var l1RequestRetryBackoffDelay: java.time.Duration = java.time.Duration.ofSeconds(1) var l1RequestRetryBackoffDelay: java.time.Duration = java.time.Duration.ofSeconds(1)
@@ -141,9 +141,9 @@ class PluginCliOptions {
names = ["--$cliOptionsPrefix-l1-retry-timeout"], names = ["--$cliOptionsPrefix-l1-retry-timeout"],
description = [ description = [
"L1 RPC api stop retrying as soon as timeout has elapsed or limit is reached", "L1 RPC api stop retrying as soon as timeout has elapsed or limit is reached",
"default will retry indefinitely" "default will retry indefinitely",
], ],
required = false required = false,
) )
var l1RequestRetryTimeout: java.time.Duration? = null var l1RequestRetryTimeout: java.time.Duration? = null
@@ -151,37 +151,37 @@ class PluginCliOptions {
names = ["--$cliOptionsPrefix-l1-retry-limit"], names = ["--$cliOptionsPrefix-l1-retry-limit"],
description = [ description = [
"L1 RPC api stop retrying when limit is reached or timeout has elapsed", "L1 RPC api stop retrying when limit is reached or timeout has elapsed",
"default will retry indefinitely" "default will retry indefinitely",
], ],
required = false required = false,
) )
var l1RequestRetryLimit: Int? = null var l1RequestRetryLimit: Int? = null
@CommandLine.Option( @CommandLine.Option(
names = ["--$cliOptionsPrefix-shomei-endpoint"], names = ["--$cliOptionsPrefix-shomei-endpoint"],
description = ["shomei (state manager) endpoint"], description = ["shomei (state manager) endpoint"],
required = true required = true,
) )
lateinit var shomeiEndpoint: URI lateinit var shomeiEndpoint: URI
@CommandLine.Option( @CommandLine.Option(
names = ["--$cliOptionsPrefix-blobscan-endpoint"], names = ["--$cliOptionsPrefix-blobscan-endpoint"],
description = ["blobscan api endpoint"], description = ["blobscan api endpoint"],
required = true required = true,
) )
lateinit var blobscanEndpoint: URI lateinit var blobscanEndpoint: URI
@CommandLine.Option( @CommandLine.Option(
names = ["--$cliOptionsPrefix-blobscan-retry-backoff-delay"], names = ["--$cliOptionsPrefix-blobscan-retry-backoff-delay"],
description = ["blobscan api retry backoff delay, default 1s"], description = ["blobscan api retry backoff delay, default 1s"],
required = false required = false,
) )
var blobscanRequestRetryBackoffDelay: java.time.Duration = java.time.Duration.ofSeconds(1) var blobscanRequestRetryBackoffDelay: java.time.Duration = java.time.Duration.ofSeconds(1)
@CommandLine.Option( @CommandLine.Option(
names = ["--$cliOptionsPrefix-blobscan-ratelimit-backoff-delay"], names = ["--$cliOptionsPrefix-blobscan-ratelimit-backoff-delay"],
description = ["blobscan api retry ratelimit backoff delay, default is disabled"], description = ["blobscan api retry ratelimit backoff delay, default is disabled"],
required = false required = false,
) )
var blobscanRequestRatelimitBackoffDelay: java.time.Duration? = null var blobscanRequestRatelimitBackoffDelay: java.time.Duration? = null
@@ -189,9 +189,9 @@ class PluginCliOptions {
names = ["--$cliOptionsPrefix-blobscan-retry-timeout"], names = ["--$cliOptionsPrefix-blobscan-retry-timeout"],
description = [ description = [
"Blobscan api stop retrying as soon as timeout has elapsed or limit is reached.", "Blobscan api stop retrying as soon as timeout has elapsed or limit is reached.",
"default will retry indefinitely" "default will retry indefinitely",
], ],
required = false required = false,
) )
var blobscanRequestRetryTimeout: java.time.Duration? = null var blobscanRequestRetryTimeout: java.time.Duration? = null
@@ -199,9 +199,9 @@ class PluginCliOptions {
names = ["--$cliOptionsPrefix-blobscan-retry-limit"], names = ["--$cliOptionsPrefix-blobscan-retry-limit"],
description = [ description = [
"Blobscan api stop retrying when limit is reached or timeout has elapsed", "Blobscan api stop retrying when limit is reached or timeout has elapsed",
"default will retry indefinitely" "default will retry indefinitely",
], ],
required = false required = false,
) )
var blobscanRequestRetryLimit: Int? = null var blobscanRequestRetryLimit: Int? = null
@@ -209,10 +209,10 @@ class PluginCliOptions {
names = ["--$cliOptionsPrefix-overriding-recovery-start-block-number"], names = ["--$cliOptionsPrefix-overriding-recovery-start-block-number"],
description = [ description = [
"Tries to force the recovery start block number to the given value. " + "Tries to force the recovery start block number to the given value. " +
"This is mean for testing purposes, not production. Must be greater than or equal to 1." "This is mean for testing purposes, not production. Must be greater than or equal to 1.",
], ],
defaultValue = "\${env:STATERECOVERY_OVERRIDE_START_BLOCK_NUMBER}", defaultValue = "\${env:STATERECOVERY_OVERRIDE_START_BLOCK_NUMBER}",
required = false required = false,
) )
var overridingRecoveryStartBlockNumber: Long? = null var overridingRecoveryStartBlockNumber: Long? = null
@@ -220,10 +220,10 @@ class PluginCliOptions {
names = ["--$cliOptionsPrefix-debug-force-sync-stop-block-number"], names = ["--$cliOptionsPrefix-debug-force-sync-stop-block-number"],
description = [ description = [
"Forces Besu to stop syncing at the given block number. " + "Forces Besu to stop syncing at the given block number. " +
"This is mean for testing purposes, not production. Must be greater than or equal to 1." "This is mean for testing purposes, not production. Must be greater than or equal to 1.",
], ],
defaultValue = "\${env:STATERECOVERY_DEBUG_FORCE_STOP_SYNC_BLOCK_NUMBER}", defaultValue = "\${env:STATERECOVERY_DEBUG_FORCE_STOP_SYNC_BLOCK_NUMBER}",
required = false required = false,
) )
var debugForceSyncStopBlockNumber: Long? = null var debugForceSyncStopBlockNumber: Long? = null
@@ -252,25 +252,25 @@ class PluginCliOptions {
l1RequestRetryConfig = RetryConfig( l1RequestRetryConfig = RetryConfig(
backoffDelay = l1RequestRetryBackoffDelay.toKotlinDuration(), backoffDelay = l1RequestRetryBackoffDelay.toKotlinDuration(),
timeout = l1RequestRetryTimeout?.toKotlinDuration(), timeout = l1RequestRetryTimeout?.toKotlinDuration(),
maxRetries = l1RequestRetryLimit?.toUInt() maxRetries = l1RequestRetryLimit?.toUInt(),
), ),
blobscanEndpoint = blobscanEndpoint, blobscanEndpoint = blobscanEndpoint,
blobScanRequestRetryConfig = RetryConfig( blobScanRequestRetryConfig = RetryConfig(
backoffDelay = blobscanRequestRetryBackoffDelay.toKotlinDuration(), backoffDelay = blobscanRequestRetryBackoffDelay.toKotlinDuration(),
timeout = blobscanRequestRetryTimeout?.toKotlinDuration(), timeout = blobscanRequestRetryTimeout?.toKotlinDuration(),
maxRetries = blobscanRequestRetryLimit?.toUInt() maxRetries = blobscanRequestRetryLimit?.toUInt(),
), ),
blobscanRequestRatelimitBackoffDelay = blobscanRequestRatelimitBackoffDelay?.toKotlinDuration(), blobscanRequestRatelimitBackoffDelay = blobscanRequestRatelimitBackoffDelay?.toKotlinDuration(),
shomeiEndpoint = shomeiEndpoint, shomeiEndpoint = shomeiEndpoint,
overridingRecoveryStartBlockNumber = overridingRecoveryStartBlockNumber?.toULong(), overridingRecoveryStartBlockNumber = overridingRecoveryStartBlockNumber?.toULong(),
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber?.toULong() debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber?.toULong(),
) )
} }
class AddressConverter : CommandLine.ITypeConverter<Address> { class AddressConverter : CommandLine.ITypeConverter<Address> {
override fun convert(value: String): Address { override fun convert(value: String): Address {
return Address.fromHexStringStrict(value) ?: throw CommandLine.TypeConversionException( return Address.fromHexStringStrict(value) ?: throw CommandLine.TypeConversionException(
"Invalid address: $value" "Invalid address: $value",
) )
} }
} }

View File

@@ -16,7 +16,7 @@ class RecoveryModeManager(
private val miningService: MiningService, private val miningService: MiningService,
private val recoveryStatePersistence: RecoveryStatusPersistence, private val recoveryStatePersistence: RecoveryStatusPersistence,
private val debugForceSyncStopBlockNumber: ULong? = null, private val debugForceSyncStopBlockNumber: ULong? = null,
headBlockNumber: ULong headBlockNumber: ULong,
) : ) :
BesuEvents.BlockAddedListener { BesuEvents.BlockAddedListener {
private val log: Logger = LogManager.getLogger(RecoveryModeManager::class.java.name) private val log: Logger = LogManager.getLogger(RecoveryModeManager::class.java.name)
@@ -37,7 +37,7 @@ class RecoveryModeManager(
log.info( log.info(
"enabling recovery mode immediately at blockNumber={} recoveryTargetBlockNumber={}", "enabling recovery mode immediately at blockNumber={} recoveryTargetBlockNumber={}",
headBlockNumber, headBlockNumber,
targetBlockNumber targetBlockNumber,
) )
switchToRecoveryMode() switchToRecoveryMode()
} }
@@ -56,14 +56,14 @@ class RecoveryModeManager(
log.info( log.info(
"Stopping synchronization services at block={} recoveryTargetBlockNumber={} was reached", "Stopping synchronization services at block={} recoveryTargetBlockNumber={} was reached",
headBlockNumber, headBlockNumber,
targetBlockNumber targetBlockNumber,
) )
switchToRecoveryMode() switchToRecoveryMode()
} else if (debugForceSyncStopBlockNumber != null && headBlockNumber >= debugForceSyncStopBlockNumber) { } else if (debugForceSyncStopBlockNumber != null && headBlockNumber >= debugForceSyncStopBlockNumber) {
log.info( log.info(
"Stopping synchronization services at block={} debugForceSyncStopBlockNumber={}", "Stopping synchronization services at block={} debugForceSyncStopBlockNumber={}",
headBlockNumber, headBlockNumber,
debugForceSyncStopBlockNumber debugForceSyncStopBlockNumber,
) )
stopBesuServices() stopBesuServices()
} }
@@ -71,7 +71,7 @@ class RecoveryModeManager(
private fun hasReachedTargetBlock( private fun hasReachedTargetBlock(
headBlockNumber: ULong = this.headBlockNumber, headBlockNumber: ULong = this.headBlockNumber,
targetBlockNumber: ULong? = this.targetBlockNumber targetBlockNumber: ULong? = this.targetBlockNumber,
): Boolean { ): Boolean {
return (headBlockNumber + 1u) >= (targetBlockNumber ?: ULong.MAX_VALUE) return (headBlockNumber + 1u) >= (targetBlockNumber ?: ULong.MAX_VALUE)
} }

View File

@@ -25,7 +25,7 @@ object TransactionMapper {
*/ */
fun mapToBesu( fun mapToBesu(
transaction: TransactionFromL1RecoveredData, transaction: TransactionFromL1RecoveredData,
chainId: ULong chainId: ULong,
): Transaction { ): Transaction {
val builder = Transaction.builder() val builder = Transaction.builder()
builder builder
@@ -48,13 +48,13 @@ object TransactionMapper {
} }
private fun mapAccessListEntries( private fun mapAccessListEntries(
accessList: List<AccessTuple>? accessList: List<AccessTuple>?,
): List<AccessListEntry>? { ): List<AccessListEntry>? {
return accessList return accessList
?.map { accessTupleParameter -> ?.map { accessTupleParameter ->
AccessListEntry.createAccessListEntry( AccessListEntry.createAccessListEntry(
accessTupleParameter.address.toBesuAddress(), accessTupleParameter.address.toBesuAddress(),
accessTupleParameter.storageKeys.map { it.encodeHex() } accessTupleParameter.storageKeys.map { it.encodeHex() },
) )
} }
} }
@@ -69,7 +69,7 @@ object TransactionMapper {
*/ */
fun mapToBesu( fun mapToBesu(
transactions: List<TransactionFromL1RecoveredData>, transactions: List<TransactionFromL1RecoveredData>,
defaultChainId: ULong defaultChainId: ULong,
): List<Transaction> { ): List<Transaction> {
return transactions.map { tx -> mapToBesu(tx, defaultChainId) } return transactions.map { tx -> mapToBesu(tx, defaultChainId) }
} }

View File

@@ -15,16 +15,16 @@ class BlockHashLookupWithRecoverySupportTest {
lookback.addLookbackHashes( lookback.addLookbackHashes(
mapOf( mapOf(
1UL to hashOf(1UL), 1UL to hashOf(1UL),
2UL to hashOf(3UL) 2UL to hashOf(3UL),
) ),
) )
assertThatThrownBy { assertThatThrownBy {
lookback.addLookbackHashes( lookback.addLookbackHashes(
mapOf( mapOf(
1UL to hashOf(1UL), 1UL to hashOf(1UL),
3UL to hashOf(3UL) 3UL to hashOf(3UL),
) ),
) )
} }
.isInstanceOf(IllegalArgumentException::class.java) .isInstanceOf(IllegalArgumentException::class.java)
@@ -34,7 +34,7 @@ class BlockHashLookupWithRecoverySupportTest {
@Test @Test
fun `addHeadBlockHash should update and prune the lookback hashes outside the lookback window`() { fun `addHeadBlockHash should update and prune the lookback hashes outside the lookback window`() {
val lookback = BlockHashLookupWithRecoverySupport( val lookback = BlockHashLookupWithRecoverySupport(
lookbackWindow = 3UL lookbackWindow = 3UL,
) )
lookback.addHeadBlockHash(0UL, hashOf(123UL)) lookback.addHeadBlockHash(0UL, hashOf(123UL))

View File

@@ -24,11 +24,11 @@ class StaticVertxHttpRequestRateLimiter(
.div(5) .div(5)
.coerceAtLeast(1.milliseconds), .coerceAtLeast(1.milliseconds),
private val requestLogFormatter: VertxHttpLoggingFormatter, private val requestLogFormatter: VertxHttpLoggingFormatter,
private val logger: Logger = LogManager.getLogger(StaticVertxHttpRequestRateLimiter::class.java) private val logger: Logger = LogManager.getLogger(StaticVertxHttpRequestRateLimiter::class.java),
) : VertxHttpRequestSender { ) : VertxHttpRequestSender {
private data class RequestAndFutureResponse( private data class RequestAndFutureResponse(
val request: HttpRequest<Buffer>, val request: HttpRequest<Buffer>,
val future: SafeFuture<HttpResponse<Buffer>> val future: SafeFuture<HttpResponse<Buffer>>,
) )
private val rateLimitPerSecond = 1.seconds.div(rateLimitBackoffDelay).toInt() private val rateLimitPerSecond = 1.seconds.div(rateLimitBackoffDelay).toInt()
@@ -54,7 +54,7 @@ class StaticVertxHttpRequestRateLimiter(
rateLimitPerSecond, rateLimitPerSecond,
requestQueue.size, requestQueue.size,
rateLimitBackoffDelay - elapsedTimeSinceLastRequest, rateLimitBackoffDelay - elapsedTimeSinceLastRequest,
requestLogFormatter.toLogString(requestQueue.peek().request) requestLogFormatter.toLogString(requestQueue.peek().request),
) )
return return
} }
@@ -93,7 +93,7 @@ class StaticVertxHttpRequestRateLimiter(
rateLimitPerSecond, rateLimitPerSecond,
requestQueue.size, requestQueue.size,
rateLimitBackoffDelay - lastRequestFiredTime.elapsedNow(), rateLimitBackoffDelay - lastRequestFiredTime.elapsedNow(),
requestLogFormatter.toLogString(request) requestLogFormatter.toLogString(request),
) )
requestQueue.add(req) requestQueue.add(req)

View File

@@ -9,7 +9,7 @@ interface VertxHttpLoggingFormatter {
fun toLogString( fun toLogString(
request: HttpRequest<Buffer>, request: HttpRequest<Buffer>,
response: HttpResponse<Buffer>? = null, response: HttpResponse<Buffer>? = null,
failureCause: Throwable? = null failureCause: Throwable? = null,
): String ): String
} }
@@ -22,14 +22,14 @@ fun HttpRequest<*>.fullUri(): String {
scheme, scheme,
this.host(), this.host(),
this.port(), this.port(),
path path,
) )
} }
class VertxRestLoggingFormatter( class VertxRestLoggingFormatter(
private val includeFullUri: Boolean = false, private val includeFullUri: Boolean = false,
private val uriTransformer: (String) -> String = { it }, private val uriTransformer: (String) -> String = { it },
private val responseLogMaxSize: UInt? = null private val responseLogMaxSize: UInt? = null,
) : VertxHttpLoggingFormatter { ) : VertxHttpLoggingFormatter {
fun HttpRequest<*>.uriToLog(): String { fun HttpRequest<*>.uriToLog(): String {
return if (includeFullUri) { return if (includeFullUri) {
@@ -46,14 +46,14 @@ class VertxRestLoggingFormatter(
override fun toLogString( override fun toLogString(
request: HttpRequest<Buffer>, request: HttpRequest<Buffer>,
response: HttpResponse<Buffer>?, response: HttpResponse<Buffer>?,
failureCause: Throwable? failureCause: Throwable?,
): String { ): String {
return if (failureCause != null) { return if (failureCause != null) {
String.format( String.format(
"<-- %s %s %s", "<-- %s %s %s",
request.method(), request.method(),
uriTransformer.invoke(request.uriToLog()), uriTransformer.invoke(request.uriToLog()),
failureCause.message?.let { errorMsg -> "error=$errorMsg" } ?: "" failureCause.message?.let { errorMsg -> "error=$errorMsg" } ?: "",
) )
} else { } else {
val responseToLog = response?.bodyAsString()?.let { bodyStr -> val responseToLog = response?.bodyAsString()?.let { bodyStr ->
@@ -68,7 +68,7 @@ class VertxRestLoggingFormatter(
request.method(), request.method(),
uriTransformer.invoke(request.uriToLog()), uriTransformer.invoke(request.uriToLog()),
response?.statusCode() ?: "", response?.statusCode() ?: "",
responseToLog responseToLog,
) )
} }
} }

View File

@@ -16,7 +16,7 @@ interface VertxHttpRequestSender {
* Handy to avoid creating anonymous classes. * Handy to avoid creating anonymous classes.
*/ */
class SimpleVertxHttpRequestSender( class SimpleVertxHttpRequestSender(
private val requestLogger: VertxRequestLogger private val requestLogger: VertxRequestLogger,
) : VertxHttpRequestSender { ) : VertxHttpRequestSender {
override fun makeRequest(request: HttpRequest<Buffer>): SafeFuture<HttpResponse<Buffer>> { override fun makeRequest(request: HttpRequest<Buffer>): SafeFuture<HttpResponse<Buffer>> {
requestLogger.logRequest(request) requestLogger.logRequest(request)

View File

@@ -13,7 +13,7 @@ object VertxHttpRequestSenderFactory {
rateLimitBackoffDelay: Duration? = null, rateLimitBackoffDelay: Duration? = null,
retryableErrorCodes: Set<Int> = setOf(429, 503, 504), retryableErrorCodes: Set<Int> = setOf(429, 503, 504),
logFormatter: VertxHttpLoggingFormatter, logFormatter: VertxHttpLoggingFormatter,
baseRequestSender: VertxHttpRequestSender baseRequestSender: VertxHttpRequestSender,
): VertxHttpRequestSender { ): VertxHttpRequestSender {
val rateLimitedSender = rateLimitBackoffDelay val rateLimitedSender = rateLimitBackoffDelay
?.let { ?.let {
@@ -21,7 +21,7 @@ object VertxHttpRequestSenderFactory {
vertx = vertx, vertx = vertx,
requestSender = baseRequestSender, requestSender = baseRequestSender,
rateLimitBackoffDelay = rateLimitBackoffDelay, rateLimitBackoffDelay = rateLimitBackoffDelay,
requestLogFormatter = logFormatter requestLogFormatter = logFormatter,
) )
} ?: baseRequestSender } ?: baseRequestSender
val sender = requestRetryConfig val sender = requestRetryConfig
@@ -30,7 +30,7 @@ object VertxHttpRequestSenderFactory {
vertx = vertx, vertx = vertx,
requestSender = rateLimitedSender, requestSender = rateLimitedSender,
requestRetryConfig = requestRetryConfig, requestRetryConfig = requestRetryConfig,
retryableErrorCodes = retryableErrorCodes retryableErrorCodes = retryableErrorCodes,
) )
} ?: rateLimitedSender } ?: rateLimitedSender
@@ -45,13 +45,13 @@ object VertxHttpRequestSenderFactory {
requestResponseLogLevel: Level = Level.TRACE, requestResponseLogLevel: Level = Level.TRACE,
failuresLogLevel: Level = Level.DEBUG, failuresLogLevel: Level = Level.DEBUG,
retryableErrorCodes: Set<Int> = setOf(429, 503, 504), retryableErrorCodes: Set<Int> = setOf(429, 503, 504),
logFormatter: VertxHttpLoggingFormatter logFormatter: VertxHttpLoggingFormatter,
): VertxHttpRequestSender { ): VertxHttpRequestSender {
val requestLogger = VertxRestRequestLogger( val requestLogger = VertxRestRequestLogger(
log = logger, log = logger,
requestResponseLogLevel = requestResponseLogLevel, requestResponseLogLevel = requestResponseLogLevel,
failuresLogLevel = failuresLogLevel, failuresLogLevel = failuresLogLevel,
logFormatter = logFormatter logFormatter = logFormatter,
) )
return createWithBaseSender( return createWithBaseSender(
vertx = vertx, vertx = vertx,
@@ -59,7 +59,7 @@ object VertxHttpRequestSenderFactory {
rateLimitBackoffDelay = rateLimitBackoffDelay, rateLimitBackoffDelay = rateLimitBackoffDelay,
retryableErrorCodes = retryableErrorCodes, retryableErrorCodes = retryableErrorCodes,
logFormatter = logFormatter, logFormatter = logFormatter,
baseRequestSender = SimpleVertxHttpRequestSender(requestLogger) baseRequestSender = SimpleVertxHttpRequestSender(requestLogger),
) )
} }
} }

View File

@@ -11,7 +11,7 @@ interface VertxRequestLogger {
fun logResponse( fun logResponse(
request: HttpRequest<Buffer>, request: HttpRequest<Buffer>,
response: HttpResponse<Buffer>? = null, response: HttpResponse<Buffer>? = null,
failureCause: Throwable? = null failureCause: Throwable? = null,
) )
} }
@@ -19,18 +19,18 @@ class VertxRestRequestLogger(
private val log: Logger, private val log: Logger,
private val logFormatter: VertxHttpLoggingFormatter, private val logFormatter: VertxHttpLoggingFormatter,
private val requestResponseLogLevel: Level = Level.TRACE, private val requestResponseLogLevel: Level = Level.TRACE,
private val failuresLogLevel: Level = Level.DEBUG private val failuresLogLevel: Level = Level.DEBUG,
) : VertxRequestLogger { ) : VertxRequestLogger {
constructor( constructor(
log: Logger, log: Logger,
responseLogMaxSize: UInt? = null, responseLogMaxSize: UInt? = null,
requestResponseLogLevel: Level = Level.TRACE, requestResponseLogLevel: Level = Level.TRACE,
failuresLogLevel: Level = Level.DEBUG failuresLogLevel: Level = Level.DEBUG,
) : this( ) : this(
log = log, log = log,
logFormatter = VertxRestLoggingFormatter(responseLogMaxSize = responseLogMaxSize), logFormatter = VertxRestLoggingFormatter(responseLogMaxSize = responseLogMaxSize),
requestResponseLogLevel = requestResponseLogLevel, requestResponseLogLevel = requestResponseLogLevel,
failuresLogLevel = failuresLogLevel failuresLogLevel = failuresLogLevel,
) )
private fun logRequest(request: HttpRequest<Buffer>, logLevel: Level = requestResponseLogLevel) { private fun logRequest(request: HttpRequest<Buffer>, logLevel: Level = requestResponseLogLevel) {
@@ -46,7 +46,7 @@ class VertxRestRequestLogger(
override fun logResponse( override fun logResponse(
request: HttpRequest<Buffer>, request: HttpRequest<Buffer>,
response: HttpResponse<Buffer>?, response: HttpResponse<Buffer>?,
failureCause: Throwable? failureCause: Throwable?,
) { ) {
val isError = response?.statusCode()?.let(::isNotSuccessStatusCode) ?: true val isError = response?.statusCode()?.let(::isNotSuccessStatusCode) ?: true
val logLevel = if (isError) failuresLogLevel else requestResponseLogLevel val logLevel = if (isError) failuresLogLevel else requestResponseLogLevel

View File

@@ -17,15 +17,15 @@ class VertxRequestRetrier(
backoffDelay = requestRetryConfig.backoffDelay, backoffDelay = requestRetryConfig.backoffDelay,
maxRetries = requestRetryConfig.maxRetries?.toInt(), maxRetries = requestRetryConfig.maxRetries?.toInt(),
timeout = requestRetryConfig.timeout, timeout = requestRetryConfig.timeout,
vertx = vertx vertx = vertx,
) ),
) : VertxHttpRequestSender { ) : VertxHttpRequestSender {
override fun makeRequest(request: HttpRequest<Buffer>): SafeFuture<HttpResponse<Buffer>> { override fun makeRequest(request: HttpRequest<Buffer>): SafeFuture<HttpResponse<Buffer>> {
return asyncRetryer return asyncRetryer
.retry( .retry(
stopRetriesPredicate = { response: HttpResponse<Buffer> -> stopRetriesPredicate = { response: HttpResponse<Buffer> ->
response.statusCode() !in retryableErrorCodes response.statusCode() !in retryableErrorCodes
} },
) { ) {
requestSender.makeRequest(request) requestSender.makeRequest(request)
} }

View File

@@ -20,7 +20,7 @@ import kotlin.time.Duration
class BlobScanClient( class BlobScanClient(
private val restClient: RestClient<JsonObject>, private val restClient: RestClient<JsonObject>,
private val log: Logger = LogManager.getLogger(BlobScanClient::class.java) private val log: Logger = LogManager.getLogger(BlobScanClient::class.java),
) : BlobFetcher { ) : BlobFetcher {
fun getBlobById(id: String): SafeFuture<ByteArray> { fun getBlobById(id: String): SafeFuture<ByteArray> {
return restClient return restClient
@@ -31,7 +31,7 @@ class BlobScanClient(
} else { } else {
throw RuntimeException( throw RuntimeException(
"error fetching blobId=$id " + "error fetching blobId=$id " +
"errorMessage=${response.body?.getString("message") ?: ""}" "errorMessage=${response.body?.getString("message") ?: ""}",
) )
} }
} }
@@ -48,7 +48,7 @@ class BlobScanClient(
requestRetryConfig: RetryConfig, requestRetryConfig: RetryConfig,
rateLimitBackoffDelay: Duration? = null, rateLimitBackoffDelay: Duration? = null,
logger: Logger = LogManager.getLogger(BlobScanClient::class.java), logger: Logger = LogManager.getLogger(BlobScanClient::class.java),
responseLogMaxSize: UInt? = 1000u responseLogMaxSize: UInt? = 1000u,
): BlobScanClient { ): BlobScanClient {
val logFormatter = VertxRestLoggingFormatter(responseLogMaxSize = responseLogMaxSize) val logFormatter = VertxRestLoggingFormatter(responseLogMaxSize = responseLogMaxSize)
@@ -61,16 +61,16 @@ class BlobScanClient(
logger = logger, logger = logger,
requestResponseLogLevel = Level.DEBUG, requestResponseLogLevel = Level.DEBUG,
failuresLogLevel = Level.DEBUG, failuresLogLevel = Level.DEBUG,
logFormatter = logFormatter logFormatter = logFormatter,
) )
val restClient = VertxRestClient( val restClient = VertxRestClient(
webClient = WebClient.create(vertx, WebClientOptions().setDefaultsFrom(endpoint)), webClient = WebClient.create(vertx, WebClientOptions().setDefaultsFrom(endpoint)),
responseParser = { it.toJsonObject() }, responseParser = { it.toJsonObject() },
requestSender = requestSender requestSender = requestSender,
) )
return BlobScanClient( return BlobScanClient(
restClient = restClient, restClient = restClient,
log = logger log = logger,
) )
} }
} }

View File

@@ -8,7 +8,7 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture
// TODO: move to a common module // TODO: move to a common module
data class RestResponse<T>( data class RestResponse<T>(
val statusCode: Int, val statusCode: Int,
val body: T? val body: T?,
) )
interface RestClient<Response> { interface RestClient<Response> {
@@ -20,13 +20,13 @@ class VertxRestClient<Response>(
private val webClient: WebClient, private val webClient: WebClient,
private val responseParser: (Buffer) -> Response, private val responseParser: (Buffer) -> Response,
private val requestSender: VertxHttpRequestSender, private val requestSender: VertxHttpRequestSender,
private val requestHeaders: Map<String, String> = mapOf("Accept" to "application/json") private val requestHeaders: Map<String, String> = mapOf("Accept" to "application/json"),
) : RestClient<Response> { ) : RestClient<Response> {
override fun get(path: String): SafeFuture<RestResponse<Response>> { override fun get(path: String): SafeFuture<RestResponse<Response>> {
return requestSender.makeRequest( return requestSender.makeRequest(
webClient webClient
.get(path) .get(path)
.apply { requestHeaders.forEach(::putHeader) } .apply { requestHeaders.forEach(::putHeader) },
) )
.thenApply { response -> .thenApply { response ->
val parsedResponse = response.body()?.let(responseParser) val parsedResponse = response.body()?.let(responseParser)

View File

@@ -16,17 +16,25 @@ import kotlin.time.TimeSource
fun httpResponse( fun httpResponse(
statusCode: Int = 200, statusCode: Int = 200,
statusMessage: String = "OK", statusMessage: String = "OK",
body: Buffer = Buffer.buffer() body: Buffer = Buffer.buffer(),
): HttpResponse<Buffer> { ): HttpResponse<Buffer> {
return HttpResponseImpl( return HttpResponseImpl(
/* version = */ HttpVersion.HTTP_1_1, /* version = */
/* statusCode = */ statusCode, HttpVersion.HTTP_1_1,
/* statusMessage = */ statusMessage, /* statusCode = */
/* headers = */ HeadersMultiMap(), statusCode,
/* trailers = */ HeadersMultiMap(), /* statusMessage = */
/* cookies = */ emptyList<String>(), statusMessage,
/* body = */ body, /* headers = */
/* redirects = */ emptyList<String>() HeadersMultiMap(),
/* trailers = */
HeadersMultiMap(),
/* cookies = */
emptyList<String>(),
/* body = */
body,
/* redirects = */
emptyList<String>(),
) )
} }
@@ -35,8 +43,8 @@ class FakeRequestSender(
VertxRestRequestLogger( VertxRestRequestLogger(
responseLogMaxSize = null, responseLogMaxSize = null,
requestResponseLogLevel = Level.DEBUG, requestResponseLogLevel = Level.DEBUG,
log = LogManager.getLogger(FakeRequestSender::class.java) log = LogManager.getLogger(FakeRequestSender::class.java),
) ),
) : VertxHttpRequestSender { ) : VertxHttpRequestSender {
private val monotonicClock = TimeSource.Monotonic private val monotonicClock = TimeSource.Monotonic
private var lastRequestTime = monotonicClock.markNow() private var lastRequestTime = monotonicClock.markNow()

View File

@@ -23,7 +23,7 @@ class StaticVertxHttpRequestRateLimiterTest {
vertx = vertx, vertx = vertx,
requestSender = reqSender, requestSender = reqSender,
rateLimitBackoffDelay = rateLimitBackoffDelay, rateLimitBackoffDelay = rateLimitBackoffDelay,
requestLogFormatter = VertxRestLoggingFormatter() requestLogFormatter = VertxRestLoggingFormatter(),
) )
} }

View File

@@ -28,10 +28,10 @@ class VertxHttpRequestRateLimiterAndRetryTest {
requestRetryConfig = RetryConfig( requestRetryConfig = RetryConfig(
maxRetries = 5u, maxRetries = 5u,
backoffDelay = 10.milliseconds, backoffDelay = 10.milliseconds,
timeout = rateLimitBackoffDelay * 30 timeout = rateLimitBackoffDelay * 30,
), ),
rateLimitBackoffDelay = rateLimitBackoffDelay, rateLimitBackoffDelay = rateLimitBackoffDelay,
logFormatter = VertxRestLoggingFormatter(responseLogMaxSize = 1000u) logFormatter = VertxRestLoggingFormatter(responseLogMaxSize = 1000u),
) )
// Warn: this does not work in io.github.hakky54:logcaptor // Warn: this does not work in io.github.hakky54:logcaptor
// don't have time to dig into it now. disabling it for now // don't have time to dig into it now. disabling it for now

View File

@@ -13,7 +13,7 @@ class VertxRestLoggingFormatterTest {
val request = WebClient.create( val request = WebClient.create(
Vertx.vertx(), Vertx.vertx(),
WebClientOptions() WebClientOptions()
.setDefaultsFrom(URI("http://service:9876/")) .setDefaultsFrom(URI("http://service:9876/")),
) )
.get("/users/1?appKey=SOME_APP_KEY") .get("/users/1?appKey=SOME_APP_KEY")
@@ -21,7 +21,7 @@ class VertxRestLoggingFormatterTest {
return VertxRestLoggingFormatter( return VertxRestLoggingFormatter(
includeFullUri = includeFullUri, includeFullUri = includeFullUri,
uriTransformer = { it.replace("SOME_APP_KEY", "***") }, uriTransformer = { it.replace("SOME_APP_KEY", "***") },
responseLogMaxSize = null responseLogMaxSize = null,
) )
} }
@@ -39,7 +39,7 @@ class VertxRestLoggingFormatterTest {
val response = httpResponse( val response = httpResponse(
statusCode = 200, statusCode = 200,
statusMessage = "OK", statusMessage = "OK",
body = Buffer.buffer("some-response-body") body = Buffer.buffer("some-response-body"),
) )
assertThat(formatter(includeFullUri = false).toLogString(request, response)) assertThat(formatter(includeFullUri = false).toLogString(request, response))

View File

@@ -21,7 +21,7 @@ class VertxRestRequestLoggerTest {
override fun toLogString( override fun toLogString(
request: HttpRequest<Buffer>, request: HttpRequest<Buffer>,
response: HttpResponse<Buffer>?, response: HttpResponse<Buffer>?,
failureCause: Throwable? failureCause: Throwable?,
): String { ): String {
return "response-log-string" return "response-log-string"
} }
@@ -29,14 +29,14 @@ class VertxRestRequestLoggerTest {
fun setUpLogger( fun setUpLogger(
// we need to use a different logger name for each test // we need to use a different logger name for each test
loggerName: String = "request-logger-test-" + Random.nextBytes(8).encodeHex() loggerName: String = "request-logger-test-" + Random.nextBytes(8).encodeHex(),
): Pair<VertxRestRequestLogger, LogCaptor> { ): Pair<VertxRestRequestLogger, LogCaptor> {
val logCaptor: LogCaptor = LogCaptor.forName(loggerName) val logCaptor: LogCaptor = LogCaptor.forName(loggerName)
return VertxRestRequestLogger( return VertxRestRequestLogger(
log = LogManager.getLogger(loggerName), log = LogManager.getLogger(loggerName),
logFormatter = FakeLogFormatter(), logFormatter = FakeLogFormatter(),
requestResponseLogLevel = Level.TRACE, requestResponseLogLevel = Level.TRACE,
failuresLogLevel = Level.DEBUG failuresLogLevel = Level.DEBUG,
) to logCaptor ) to logCaptor
} }

View File

@@ -32,13 +32,13 @@ class BlobScanClientTest {
fun setUp(vertx: Vertx) { fun setUp(vertx: Vertx) {
wiremock = WireMockServer( wiremock = WireMockServer(
WireMockConfiguration.options() WireMockConfiguration.options()
.dynamicPort() .dynamicPort(),
) )
.apply { .apply {
addMockServiceRequestListener(object : RequestListener { addMockServiceRequestListener(object : RequestListener {
override fun requestReceived( override fun requestReceived(
request: com.github.tomakehurst.wiremock.http.Request, request: com.github.tomakehurst.wiremock.http.Request,
response: com.github.tomakehurst.wiremock.http.Response response: com.github.tomakehurst.wiremock.http.Response,
) { ) {
// to debug // to debug
// println("request: ${request.url}") // println("request: ${request.url}")
@@ -55,8 +55,8 @@ class BlobScanClientTest {
requestRetryConfig = RetryConfig( requestRetryConfig = RetryConfig(
backoffDelay = 10.milliseconds, backoffDelay = 10.milliseconds,
maxRetries = 5u, maxRetries = 5u,
timeout = 5.seconds timeout = 5.seconds,
) ),
) )
} }
@@ -78,8 +78,8 @@ class BlobScanClientTest {
.willReturn( .willReturn(
WireMock.ok() WireMock.ok()
.withHeader("Content-type", "application/json") .withHeader("Content-type", "application/json")
.withBody(successResponseBody(blobId, blobData)) .withBody(successResponseBody(blobId, blobData)),
) ),
) )
assertThat(blobScanClient.getBlobById(blobId).get().encodeHex()).isEqualTo(blobData) assertThat(blobScanClient.getBlobById(blobId).get().encodeHex()).isEqualTo(blobData)
@@ -99,9 +99,9 @@ class BlobScanClientTest {
.withBody( .withBody(
""" """
{"message":"No blob with versioned hash or kzg commitment '$blobId'.","code":"NOT_FOUND"} {"message":"No blob with versioned hash or kzg commitment '$blobId'.","code":"NOT_FOUND"}
""".trimIndent() """.trimIndent(),
) ),
) ),
) )
assertThatThrownBy { blobScanClient.getBlobById(blobId).get() } assertThatThrownBy { blobScanClient.getBlobById(blobId).get() }
@@ -117,22 +117,22 @@ class BlobScanClientTest {
WireMock.get("/blobs/$blobId") WireMock.get("/blobs/$blobId")
.inScenario("SERVER_ERROR") .inScenario("SERVER_ERROR")
.willReturn(WireMock.status(503)) .willReturn(WireMock.status(503))
.willSetStateTo("SERVER_ERROR_1") .willSetStateTo("SERVER_ERROR_1"),
) )
wiremock.stubFor( wiremock.stubFor(
WireMock.get("/blobs/$blobId") WireMock.get("/blobs/$blobId")
.inScenario("SERVER_ERROR") .inScenario("SERVER_ERROR")
.whenScenarioStateIs("SERVER_ERROR_1") .whenScenarioStateIs("SERVER_ERROR_1")
.willReturn(WireMock.status(503)) .willReturn(WireMock.status(503))
.willSetStateTo("SERVER_OK") .willSetStateTo("SERVER_OK"),
) )
wiremock.stubFor( wiremock.stubFor(
WireMock.get("/blobs/$blobId") WireMock.get("/blobs/$blobId")
.inScenario("SERVER_ERROR") .inScenario("SERVER_ERROR")
.whenScenarioStateIs("SERVER_OK") .whenScenarioStateIs("SERVER_OK")
.willReturn( .willReturn(
WireMock.okJson(successResponseBody(blobId, blobData)) WireMock.okJson(successResponseBody(blobId, blobData)),
) ),
) )
assertThat(blobScanClient.getBlobById(blobId).get().encodeHex()).isEqualTo(blobData) assertThat(blobScanClient.getBlobById(blobId).get().encodeHex()).isEqualTo(blobData)
@@ -140,7 +140,7 @@ class BlobScanClientTest {
private fun successResponseBody( private fun successResponseBody(
blobId: String, blobId: String,
blobData: String blobData: String,
): String { ): String {
return """ return """
{ {

View File

@@ -13,7 +13,7 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture
import java.net.URI import java.net.URI
class VertxTransactionDetailsClient internal constructor( class VertxTransactionDetailsClient internal constructor(
private val jsonRpcClient: JsonRpcV2Client private val jsonRpcClient: JsonRpcV2Client,
) : TransactionDetailsClient { ) : TransactionDetailsClient {
companion object { companion object {
@@ -21,14 +21,14 @@ class VertxTransactionDetailsClient internal constructor(
jsonRpcClientFactory: JsonRpcClientFactory, jsonRpcClientFactory: JsonRpcClientFactory,
endpoint: URI, endpoint: URI,
retryConfig: RequestRetryConfig, retryConfig: RequestRetryConfig,
logger: Logger = LogManager.getLogger(TransactionDetailsClient::class.java) logger: Logger = LogManager.getLogger(TransactionDetailsClient::class.java),
): VertxTransactionDetailsClient { ): VertxTransactionDetailsClient {
return VertxTransactionDetailsClient( return VertxTransactionDetailsClient(
jsonRpcClientFactory.createJsonRpcV2Client( jsonRpcClientFactory.createJsonRpcV2Client(
endpoints = listOf(endpoint), endpoints = listOf(endpoint),
retryConfig = retryConfig, retryConfig = retryConfig,
log = logger log = logger,
) ),
) )
} }
} }
@@ -44,7 +44,7 @@ class VertxTransactionDetailsClient internal constructor(
?.toList() ?.toList()
?.map { it.asText().decodeHex() } ?.map { it.asText().decodeHex() }
?: emptyList() ?: emptyList()
} },
) )
} }
} }

View File

@@ -54,7 +54,7 @@ class StateRecoveryE2ETest {
fun beforeEach(vertx: Vertx) { fun beforeEach(vertx: Vertx) {
val jsonRpcFactory = VertxHttpJsonRpcClientFactory( val jsonRpcFactory = VertxHttpJsonRpcClientFactory(
vertx = vertx, vertx = vertx,
metricsFacade = MicrometerMetricsFacade(SimpleMeterRegistry()) metricsFacade = MicrometerMetricsFacade(SimpleMeterRegistry()),
) )
stateManagerClient = StateManagerV1JsonRpcClient.create( stateManagerClient = StateManagerV1JsonRpcClient.create(
@@ -63,10 +63,10 @@ class StateRecoveryE2ETest {
maxInflightRequestsPerClient = 1U, maxInflightRequestsPerClient = 1U,
requestRetry = RequestRetryConfig( requestRetry = RequestRetryConfig(
backoffDelay = 10.milliseconds, backoffDelay = 10.milliseconds,
timeout = 2.seconds timeout = 2.seconds,
), ),
zkStateManagerVersion = "2.3.0", zkStateManagerVersion = "2.3.0",
logger = LogManager.getLogger("test.clients.l1.state-manager") logger = LogManager.getLogger("test.clients.l1.state-manager"),
) )
configureLoggers( configureLoggers(
@@ -80,7 +80,7 @@ class StateRecoveryE2ETest {
"test.clients.l1.linea-contract" to Level.INFO, "test.clients.l1.linea-contract" to Level.INFO,
"test.clients.l1.events-fetcher" to Level.INFO, "test.clients.l1.events-fetcher" to Level.INFO,
"test.clients.l1.blobscan" to Level.INFO, "test.clients.l1.blobscan" to Level.INFO,
"net.consensys.linea.contract.l1" to Level.INFO "net.consensys.linea.contract.l1" to Level.INFO,
) )
} }
@@ -89,16 +89,16 @@ class StateRecoveryE2ETest {
Runner.executeCommandFailOnNonZeroExitCode( Runner.executeCommandFailOnNonZeroExitCode(
command = "make start-env-with-staterecovery", command = "make start-env-with-staterecovery",
envVars = mapOf( envVars = mapOf(
"L1_GENESIS_TIME" to Clock.System.now().plus(5.seconds).epochSeconds.toString() "L1_GENESIS_TIME" to Clock.System.now().plus(5.seconds).epochSeconds.toString(),
), ),
timeout = 2.minutes timeout = 2.minutes,
).get() ).get()
log.debug("stack restarted") log.debug("stack restarted")
} }
@Test @Test
fun `should recover from middle of chain and be resilient to node restarts`( fun `should recover from middle of chain and be resilient to node restarts`(
vertx: Vertx vertx: Vertx,
) { ) {
// Part A: // Part A:
// we shall have multiple finalizations on L1 // we shall have multiple finalizations on L1
@@ -128,15 +128,15 @@ class StateRecoveryE2ETest {
Web3jClientManager.buildL1Client( Web3jClientManager.buildL1Client(
log = LogManager.getLogger("test.clients.l1.events-fetcher"), log = LogManager.getLogger("test.clients.l1.events-fetcher"),
requestResponseLogLevel = Level.TRACE, requestResponseLogLevel = Level.TRACE,
failuresLogLevel = Level.WARN failuresLogLevel = Level.WARN,
), ),
requestRetryConfig = RetryConfig.noRetries, requestRetryConfig = RetryConfig.noRetries,
vertx = null vertx = null,
), ),
EthLogsSearcherImpl.Config( EthLogsSearcherImpl.Config(
loopSuccessBackoffDelay = 1.milliseconds loopSuccessBackoffDelay = 1.milliseconds,
), ),
log = LogManager.getLogger("test.clients.l1.events-fetcher") log = LogManager.getLogger("test.clients.l1.events-fetcher"),
) )
val web3jElClient = createWeb3jHttpClient(executionLayerUrl) val web3jElClient = createWeb3jHttpClient(executionLayerUrl)
log.info("starting test flow: besu staterecovery block={}", web3jElClient.ethBlockNumber().send().blockNumber) log.info("starting test flow: besu staterecovery block={}", web3jElClient.ethBlockNumber().send().blockNumber)
@@ -167,7 +167,7 @@ class StateRecoveryE2ETest {
command = "make staterecovery-replay-from-block " + command = "make staterecovery-replay-from-block " +
"L1_ROLLUP_CONTRACT_ADDRESS=$localStackL1ContractAddress " + "L1_ROLLUP_CONTRACT_ADDRESS=$localStackL1ContractAddress " +
"STATERECOVERY_OVERRIDE_START_BLOCK_NUMBER=$stateRecoveryStartBlockNumber", "STATERECOVERY_OVERRIDE_START_BLOCK_NUMBER=$stateRecoveryStartBlockNumber",
log = log log = log,
).get() ).get()
// No Errors should be logged in Besu // No Errors should be logged in Besu
assertThat(getBesuErrorLogs()).isEmpty() assertThat(getBesuErrorLogs()).isEmpty()
@@ -178,7 +178,7 @@ class StateRecoveryE2ETest {
web3jElClient, web3jElClient,
stateManagerClient, stateManagerClient,
lastFinalizationA.event.endBlockNumber, lastFinalizationA.event.endBlockNumber,
lastFinalizationA.event.finalStateRootHash lastFinalizationA.event.finalStateRootHash,
) )
// No Errors should be logged in Besu // No Errors should be logged in Besu
assertThat(getBesuErrorLogs()).isEmpty() assertThat(getBesuErrorLogs()).isEmpty()
@@ -200,7 +200,7 @@ class StateRecoveryE2ETest {
web3jElClient, web3jElClient,
stateManagerClient, stateManagerClient,
lastFinalizationB.event.endBlockNumber, lastFinalizationB.event.endBlockNumber,
lastFinalizationB.event.finalStateRootHash lastFinalizationB.event.finalStateRootHash,
) )
// No Errors should be logged in Besu // No Errors should be logged in Besu
assertThat(getBesuErrorLogs()).isEmpty() assertThat(getBesuErrorLogs()).isEmpty()
@@ -210,7 +210,7 @@ class StateRecoveryE2ETest {
log.info("Restarting zkbesu-shomei node") log.info("Restarting zkbesu-shomei node")
execCommandAndAssertSuccess( execCommandAndAssertSuccess(
command = "docker restart -s 9 zkbesu-shomei-sr", command = "docker restart -s 9 zkbesu-shomei-sr",
log = log log = log,
).get() ).get()
// No Errors should be logged in Besu // No Errors should be logged in Besu
assertThat(getBesuErrorLogs()).isEmpty() assertThat(getBesuErrorLogs()).isEmpty()
@@ -237,31 +237,36 @@ class StateRecoveryE2ETest {
web3jElClient, web3jElClient,
stateManagerClient, stateManagerClient,
lastFinalizationC.event.endBlockNumber, lastFinalizationC.event.endBlockNumber,
lastFinalizationC.event.finalStateRootHash lastFinalizationC.event.finalStateRootHash,
) )
// No Errors should be logged in Besu // No Errors should be logged in Besu
assertThat(getBesuErrorLogs()).isEmpty() assertThat(getBesuErrorLogs()).isEmpty()
} }
private fun sendTxToL2( private fun sendTxToL2(
keepSendingPredicate: () -> Boolean keepSendingPredicate: () -> Boolean,
) { ) {
val account = L2AccountManager.generateAccount() val account = L2AccountManager.generateAccount()
val txManager = L2AccountManager.getTransactionManager(account) val txManager = L2AccountManager.getTransactionManager(account)
Thread { Thread {
while (keepSendingPredicate()) { while (keepSendingPredicate()) {
val txHash = txManager.sendTransaction( val txHash = txManager.sendTransaction(
/*gasPrice*/ 150UL.gwei.toBigInteger(), /*gasPrice*/
/*gasLimit*/ 25_000UL.toBigInteger(), 150UL.gwei.toBigInteger(),
/*to*/ account.address, /*gasLimit*/
/*data*/ "", 25_000UL.toBigInteger(),
/*value*/ 1UL.toBigInteger() /*to*/
account.address,
/*data*/
"",
/*value*/
1UL.toBigInteger(),
).transactionHash ).transactionHash
log.trace("sent tx to L2, txHash={}", txHash) log.trace("sent tx to L2, txHash={}", txHash)
Web3jClientManager.l2Client.waitForTxReceipt( Web3jClientManager.l2Client.waitForTxReceipt(
txHash = txHash, txHash = txHash,
timeout = 5.seconds, timeout = 5.seconds,
pollingInterval = 500.milliseconds pollingInterval = 500.milliseconds,
) )
} }
}.start() }.start()

View File

@@ -39,7 +39,7 @@ class LineaSubmissionEventsClientIntTest {
private lateinit var submissionEventsFetcher: LineaRollupSubmissionEventsClient private lateinit var submissionEventsFetcher: LineaRollupSubmissionEventsClient
private fun setupTest( private fun setupTest(
vertx: Vertx vertx: Vertx,
) { ) {
configureLoggers( configureLoggers(
rootLevel = Level.INFO, rootLevel = Level.INFO,
@@ -47,7 +47,7 @@ class LineaSubmissionEventsClientIntTest {
"test.clients.l1.executionlayer" to Level.INFO, "test.clients.l1.executionlayer" to Level.INFO,
"test.clients.l1.web3j-default" to Level.INFO, "test.clients.l1.web3j-default" to Level.INFO,
"test.clients.l1.linea-contract" to Level.INFO, "test.clients.l1.linea-contract" to Level.INFO,
"test.clients.l1.events-fetcher" to Level.DEBUG "test.clients.l1.events-fetcher" to Level.DEBUG,
) )
val rollupDeploymentFuture = ContractsManager.get() val rollupDeploymentFuture = ContractsManager.get()
@@ -57,13 +57,13 @@ class LineaSubmissionEventsClientIntTest {
blobsResponsesDir = "$testDataDir/compression/responses", blobsResponsesDir = "$testDataDir/compression/responses",
aggregationsResponsesDir = "$testDataDir/aggregation/responses", aggregationsResponsesDir = "$testDataDir/aggregation/responses",
numberOfAggregations = 7, numberOfAggregations = 7,
extraBlobsWithoutAggregation = 3 extraBlobsWithoutAggregation = 3,
) )
// wait smc deployment finishes // wait smc deployment finishes
rollupDeploymentResult = rollupDeploymentFuture.get() rollupDeploymentResult = rollupDeploymentFuture.get()
submissionEventsFetcher = createSubmissionEventsClient( submissionEventsFetcher = createSubmissionEventsClient(
vertx = vertx, vertx = vertx,
contractAddress = rollupDeploymentResult.contractAddress contractAddress = rollupDeploymentResult.contractAddress,
) )
submitBlobsAndAggregationsAndWaitExecution( submitBlobsAndAggregationsAndWaitExecution(
@@ -71,24 +71,24 @@ class LineaSubmissionEventsClientIntTest {
contractClientForAggregationSubmission = connectToLineaRollupContract( contractClientForAggregationSubmission = connectToLineaRollupContract(
contractAddress = rollupDeploymentResult.contractAddress, contractAddress = rollupDeploymentResult.contractAddress,
transactionManager = rollupDeploymentResult.rollupOperators[1].txManager, transactionManager = rollupDeploymentResult.rollupOperators[1].txManager,
smartContractErrors = lineaRollupContractErrors smartContractErrors = lineaRollupContractErrors,
), ),
aggregationsAndBlobs = aggregationsAndBlobs, aggregationsAndBlobs = aggregationsAndBlobs,
blobChunksMaxSize = 9, blobChunksMaxSize = 9,
l1Web3jClient = Web3jClientManager.l1Client, l1Web3jClient = Web3jClientManager.l1Client,
waitTimeout = 4.minutes waitTimeout = 4.minutes,
) )
} }
private fun createSubmissionEventsClient( private fun createSubmissionEventsClient(
vertx: Vertx, vertx: Vertx,
contractAddress: String contractAddress: String,
): LineaRollupSubmissionEventsClient { ): LineaRollupSubmissionEventsClient {
val log = LogManager.getLogger("test.clients.l1.events-fetcher") val log = LogManager.getLogger("test.clients.l1.events-fetcher")
val eventsFetcherWeb3jClient = Web3jClientManager.buildL1Client( val eventsFetcherWeb3jClient = Web3jClientManager.buildL1Client(
log = log, log = log,
requestResponseLogLevel = Level.DEBUG, requestResponseLogLevel = Level.DEBUG,
failuresLogLevel = Level.WARN failuresLogLevel = Level.WARN,
) )
return LineaSubmissionEventsClientImpl( return LineaSubmissionEventsClientImpl(
logsSearcher = EthLogsSearcherImpl( logsSearcher = EthLogsSearcherImpl(
@@ -96,16 +96,16 @@ class LineaSubmissionEventsClientIntTest {
ethApiClient = createEthApiClient( ethApiClient = createEthApiClient(
web3jClient = eventsFetcherWeb3jClient, web3jClient = eventsFetcherWeb3jClient,
requestRetryConfig = RetryConfig.noRetries, requestRetryConfig = RetryConfig.noRetries,
vertx = null vertx = null,
), ),
config = EthLogsSearcherImpl.Config( config = EthLogsSearcherImpl.Config(
loopSuccessBackoffDelay = 1.milliseconds loopSuccessBackoffDelay = 1.milliseconds,
), ),
log = log log = log,
), ),
smartContractAddress = contractAddress, smartContractAddress = contractAddress,
l1LatestSearchBlock = BlockParameter.Tag.LATEST, l1LatestSearchBlock = BlockParameter.Tag.LATEST,
logsBlockChunkSize = 100 logsBlockChunkSize = 100,
) )
} }
@@ -125,8 +125,8 @@ class LineaSubmissionEventsClientIntTest {
submissionEventsFetcher submissionEventsFetcher
.findFinalizationAndDataSubmissionV3Events( .findFinalizationAndDataSubmissionV3Events(
fromL1BlockNumber = BlockParameter.Tag.EARLIEST, fromL1BlockNumber = BlockParameter.Tag.EARLIEST,
finalizationStartBlockNumber = expectedFinalizationEvent.startBlockNumber finalizationStartBlockNumber = expectedFinalizationEvent.startBlockNumber,
) ),
) )
.succeedsWithin(1.minutes.toJavaDuration()) .succeedsWithin(1.minutes.toJavaDuration())
.extracting { submissionEvents -> .extracting { submissionEvents ->
@@ -146,8 +146,8 @@ class LineaSubmissionEventsClientIntTest {
submissionEventsFetcher submissionEventsFetcher
.findFinalizationAndDataSubmissionV3Events( .findFinalizationAndDataSubmissionV3Events(
fromL1BlockNumber = BlockParameter.Tag.EARLIEST, fromL1BlockNumber = BlockParameter.Tag.EARLIEST,
finalizationStartBlockNumber = invalidStartBlockNumber finalizationStartBlockNumber = invalidStartBlockNumber,
).get() ).get(),
) )
.isNull() .isNull()
} }
@@ -159,7 +159,7 @@ class LineaSubmissionEventsClientIntTest {
submissionEventsFetcher submissionEventsFetcher
.findFinalizationAndDataSubmissionV3EventsContainingL2BlockNumber( .findFinalizationAndDataSubmissionV3EventsContainingL2BlockNumber(
fromL1BlockNumber = BlockParameter.Tag.EARLIEST, fromL1BlockNumber = BlockParameter.Tag.EARLIEST,
l2BlockNumber = invalidStartBlockNumber l2BlockNumber = invalidStartBlockNumber,
).get() ).get()
.also { result -> .also { result ->
assertThat(result).isNotNull assertThat(result).isNotNull
@@ -169,7 +169,7 @@ class LineaSubmissionEventsClientIntTest {
} }
private fun getExpectedSubmissionEventsFromRecords( private fun getExpectedSubmissionEventsFromRecords(
aggregationsAndBlobs: List<AggregationAndBlobs> aggregationsAndBlobs: List<AggregationAndBlobs>,
): List<Pair<DataFinalizedV3, List<DataSubmittedV3>>> { ): List<Pair<DataFinalizedV3, List<DataSubmittedV3>>> {
return aggregationsAndBlobs return aggregationsAndBlobs
.filter { it.aggregation != null } .filter { it.aggregation != null }
@@ -180,7 +180,7 @@ class LineaSubmissionEventsClientIntTest {
DataSubmittedV3( DataSubmittedV3(
parentShnarf = blobsChunk.first().blobCompressionProof!!.prevShnarf, parentShnarf = blobsChunk.first().blobCompressionProof!!.prevShnarf,
shnarf = blobsChunk.last().expectedShnarf, shnarf = blobsChunk.last().expectedShnarf,
finalStateRootHash = blobsChunk.last().blobCompressionProof!!.finalStateRootHash finalStateRootHash = blobsChunk.last().blobCompressionProof!!.finalStateRootHash,
) )
} }
@@ -190,7 +190,7 @@ class LineaSubmissionEventsClientIntTest {
endBlockNumber = aggregation.endBlockNumber, endBlockNumber = aggregation.endBlockNumber,
shnarf = aggBlobs.last().expectedShnarf, shnarf = aggBlobs.last().expectedShnarf,
parentStateRootHash = aggBlobs.first().blobCompressionProof!!.parentStateRootHash, parentStateRootHash = aggBlobs.first().blobCompressionProof!!.parentStateRootHash,
finalStateRootHash = aggBlobs.last().blobCompressionProof!!.finalStateRootHash finalStateRootHash = aggBlobs.last().blobCompressionProof!!.finalStateRootHash,
) to expectedDataSubmittedEvents ) to expectedDataSubmittedEvents
} }
} }

View File

@@ -65,12 +65,12 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
blobsResponsesDir = "$testDataDir/compression/responses", blobsResponsesDir = "$testDataDir/compression/responses",
aggregationsResponsesDir = "$testDataDir/aggregation/responses", aggregationsResponsesDir = "$testDataDir/aggregation/responses",
numberOfAggregations = 4, numberOfAggregations = 4,
extraBlobsWithoutAggregation = 0 extraBlobsWithoutAggregation = 0,
) )
fakeExecutionLayerClient = FakeExecutionLayerClient( fakeExecutionLayerClient = FakeExecutionLayerClient(
headBlock = BlockNumberAndHash(number = 0uL, hash = ByteArray(32) { 0 }), headBlock = BlockNumberAndHash(number = 0uL, hash = ByteArray(32) { 0 }),
initialStateRecoverStartBlockNumber = null, initialStateRecoverStartBlockNumber = null,
loggerName = "test.fake.clients.l1.fake-execution-layer" loggerName = "test.fake.clients.l1.fake-execution-layer",
) )
fakeStateManagerClient = fakeStateManagerClient =
FakeStateManagerClientBasedOnBlobsRecords(blobRecords = aggregationsAndBlobs.flatMap { it.blobs }) FakeStateManagerClientBasedOnBlobsRecords(blobRecords = aggregationsAndBlobs.flatMap { it.blobs })
@@ -84,7 +84,7 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
l1PollingInterval = 100.milliseconds, l1PollingInterval = 100.milliseconds,
l1getLogsChunkSize = 1000u, l1getLogsChunkSize = 1000u,
executionClientPollingInterval = 1.seconds, executionClientPollingInterval = 1.seconds,
smartContractAddress = rollupDeploymentResult.contractAddress smartContractAddress = rollupDeploymentResult.contractAddress,
) )
appClients = createAppClients( appClients = createAppClients(
@@ -93,14 +93,14 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
l1RpcEndpoint = URI(l1RpcUrl), l1RpcEndpoint = URI(l1RpcUrl),
l1RequestRetryConfig = RetryConfig(backoffDelay = 2.seconds), l1RequestRetryConfig = RetryConfig(backoffDelay = 2.seconds),
blobScanEndpoint = URI(blobScanUrl), blobScanEndpoint = URI(blobScanUrl),
stateManagerClientEndpoint = URI("http://it-does-not-matter:5432") stateManagerClientEndpoint = URI("http://it-does-not-matter:5432"),
) )
contractClientForBlobSubmissions = rollupDeploymentResult.rollupOperatorClient contractClientForBlobSubmissions = rollupDeploymentResult.rollupOperatorClient
contractClientForAggregationSubmissions = connectToLineaRollupContract( contractClientForAggregationSubmissions = connectToLineaRollupContract(
rollupDeploymentResult.contractAddress, rollupDeploymentResult.contractAddress,
rollupDeploymentResult.rollupOperators[1].txManager, rollupDeploymentResult.rollupOperators[1].txManager,
smartContractErrors = lineaRollupContractErrors smartContractErrors = lineaRollupContractErrors,
) )
configureLoggers( configureLoggers(
@@ -113,12 +113,12 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
"test.fake.clients.l1.fake-execution-layer" to Level.DEBUG, "test.fake.clients.l1.fake-execution-layer" to Level.DEBUG,
"test.clients.l1.web3j-default" to Level.INFO, "test.clients.l1.web3j-default" to Level.INFO,
"test.clients.l1.web3j.receipt-poller" to Level.INFO, "test.clients.l1.web3j.receipt-poller" to Level.INFO,
"linea.staterecovery.datafetching" to Level.INFO "linea.staterecovery.datafetching" to Level.INFO,
) )
} }
fun instantiateStateRecoveryApp( fun instantiateStateRecoveryApp(
debugForceSyncStopBlockNumber: ULong? = null debugForceSyncStopBlockNumber: ULong? = null,
): StateRecoveryApp { ): StateRecoveryApp {
return StateRecoveryApp( return StateRecoveryApp(
vertx = vertx, vertx = vertx,
@@ -130,15 +130,15 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
blockHeaderStaticFields = BlockHeaderStaticFields.localDev, blockHeaderStaticFields = BlockHeaderStaticFields.localDev,
lineaContractClient = appClients.lineaContractClient, lineaContractClient = appClients.lineaContractClient,
config = appConfigs.copy( config = appConfigs.copy(
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber,
) ),
) )
} }
private fun submitDataToL1ContactAndWaitExecution( private fun submitDataToL1ContactAndWaitExecution(
aggregationsAndBlobs: List<AggregationAndBlobs> = this.aggregationsAndBlobs, aggregationsAndBlobs: List<AggregationAndBlobs> = this.aggregationsAndBlobs,
blobChunksSize: Int = 9, blobChunksSize: Int = 9,
waitTimeout: Duration = 4.minutes waitTimeout: Duration = 4.minutes,
) { ) {
submitBlobsAndAggregationsAndWaitExecution( submitBlobsAndAggregationsAndWaitExecution(
contractClientForBlobSubmission = contractClientForBlobSubmissions, contractClientForBlobSubmission = contractClientForBlobSubmissions,
@@ -148,8 +148,8 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
waitTimeout = waitTimeout, waitTimeout = waitTimeout,
l1Web3jClient = createWeb3jHttpClient( l1Web3jClient = createWeb3jHttpClient(
rpcUrl = l1RpcUrl, rpcUrl = l1RpcUrl,
log = LogManager.getLogger("test.clients.l1.web3j.receipt-poller") log = LogManager.getLogger("test.clients.l1.web3j.receipt-poller"),
) ),
) )
} }
@@ -162,7 +162,7 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
2. when state recovery enabled: 2. when state recovery enabled:
2.1 recoveryStartBlockNumber > headBlockNumber: pull for head block number until is reached and start recovery there 2.1 recoveryStartBlockNumber > headBlockNumber: pull for head block number until is reached and start recovery there
2.2 recoveryStartBlockNumber <= headBlockNumber: resume recovery from headBlockNumber 2.2 recoveryStartBlockNumber <= headBlockNumber: resume recovery from headBlockNumber
*/ */
@Test @Test
fun `when state recovery disabled and is starting from genesis`() { fun `when state recovery disabled and is starting from genesis`() {
instantiateStateRecoveryApp().start().get() instantiateStateRecoveryApp().start().get()
@@ -180,8 +180,8 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
.isEqualTo( .isEqualTo(
StateRecoveryStatus( StateRecoveryStatus(
headBlockNumber = lastAggregation!!.endBlockNumber, headBlockNumber = lastAggregation!!.endBlockNumber,
stateRecoverStartBlockNumber = 1UL stateRecoverStartBlockNumber = 1UL,
) ),
) )
} }
@@ -204,16 +204,16 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
log.debug( log.debug(
"finalizations={} finalizationToStartRecoveryFrom={}", "finalizations={} finalizationToStartRecoveryFrom={}",
aggregationsAndBlobs.map { it.aggregation?.intervalString() }, aggregationsAndBlobs.map { it.aggregation?.intervalString() },
finalizationToResumeFrom.intervalString() finalizationToResumeFrom.intervalString(),
) )
submitDataToL1ContactAndWaitExecution( submitDataToL1ContactAndWaitExecution(
aggregationsAndBlobs = finalizationsBeforeCutOff aggregationsAndBlobs = finalizationsBeforeCutOff,
) )
fakeExecutionLayerClient.headBlock = BlockNumberAndHash( fakeExecutionLayerClient.headBlock = BlockNumberAndHash(
number = 1UL, number = 1UL,
hash = ByteArray(32) { 0 } hash = ByteArray(32) { 0 },
) )
val lastFinalizedBlockNumber = finalizationsBeforeCutOff.last().aggregation!!.endBlockNumber val lastFinalizedBlockNumber = finalizationsBeforeCutOff.last().aggregation!!.endBlockNumber
@@ -227,8 +227,8 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
assertThat(fakeExecutionLayerClient.stateRecoverStatus).isEqualTo( assertThat(fakeExecutionLayerClient.stateRecoverStatus).isEqualTo(
StateRecoveryStatus( StateRecoveryStatus(
headBlockNumber = 1UL, headBlockNumber = 1UL,
stateRecoverStartBlockNumber = expectedStateRecoverStartBlockNumber stateRecoverStartBlockNumber = expectedStateRecoverStartBlockNumber,
) ),
) )
log.info("stateRecoverStatus={}", fakeExecutionLayerClient.stateRecoverStatus) log.info("stateRecoverStatus={}", fakeExecutionLayerClient.stateRecoverStatus)
} }
@@ -236,12 +236,12 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
// simulate that execution client has synced up to the last finalized block through P2P network // simulate that execution client has synced up to the last finalized block through P2P network
fakeExecutionLayerClient.headBlock = BlockNumberAndHash( fakeExecutionLayerClient.headBlock = BlockNumberAndHash(
number = lastFinalizedBlockNumber, number = lastFinalizedBlockNumber,
hash = ByteArray(32) { 0 } hash = ByteArray(32) { 0 },
) )
// continue finalizing the rest of the aggregations // continue finalizing the rest of the aggregations
submitDataToL1ContactAndWaitExecution( submitDataToL1ContactAndWaitExecution(
aggregationsAndBlobs = finalizationsAfterCutOff aggregationsAndBlobs = finalizationsAfterCutOff,
) )
val lastAggregation = aggregationsAndBlobs.findLast { it.aggregation != null }!!.aggregation val lastAggregation = aggregationsAndBlobs.findLast { it.aggregation != null }!!.aggregation
@@ -277,18 +277,18 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
log.debug( log.debug(
"finalizations={} finalizationToStartRecoveryFrom={}", "finalizations={} finalizationToStartRecoveryFrom={}",
aggregationsAndBlobs.map { it.aggregation?.intervalString() }, aggregationsAndBlobs.map { it.aggregation?.intervalString() },
finalizationToResumeFrom.intervalString() finalizationToResumeFrom.intervalString(),
) )
submitDataToL1ContactAndWaitExecution( submitDataToL1ContactAndWaitExecution(
aggregationsAndBlobs = finalizationsBeforeCutOff aggregationsAndBlobs = finalizationsBeforeCutOff,
) )
// set execution layer head block after latest finalization // set execution layer head block after latest finalization
val headBlockNumberAtStart = finalizationsBeforeCutOff.last().aggregation!!.endBlockNumber + 1UL val headBlockNumberAtStart = finalizationsBeforeCutOff.last().aggregation!!.endBlockNumber + 1UL
fakeExecutionLayerClient.headBlock = BlockNumberAndHash( fakeExecutionLayerClient.headBlock = BlockNumberAndHash(
number = headBlockNumberAtStart, number = headBlockNumberAtStart,
hash = ByteArray(32) { 0 } hash = ByteArray(32) { 0 },
) )
instantiateStateRecoveryApp().start().get() instantiateStateRecoveryApp().start().get()
await() await()
@@ -298,15 +298,15 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
assertThat(fakeExecutionLayerClient.stateRecoverStatus).isEqualTo( assertThat(fakeExecutionLayerClient.stateRecoverStatus).isEqualTo(
StateRecoveryStatus( StateRecoveryStatus(
headBlockNumber = headBlockNumberAtStart, headBlockNumber = headBlockNumberAtStart,
stateRecoverStartBlockNumber = headBlockNumberAtStart + 1UL stateRecoverStartBlockNumber = headBlockNumberAtStart + 1UL,
) ),
) )
log.debug("stateRecoverStatus={}", fakeExecutionLayerClient.stateRecoverStatus) log.debug("stateRecoverStatus={}", fakeExecutionLayerClient.stateRecoverStatus)
} }
// continue finalizing the rest of the aggregations // continue finalizing the rest of the aggregations
submitDataToL1ContactAndWaitExecution( submitDataToL1ContactAndWaitExecution(
aggregationsAndBlobs = finalizationsAfterCutOff aggregationsAndBlobs = finalizationsAfterCutOff,
) )
val lastAggregation = aggregationsAndBlobs.findLast { it.aggregation != null }!!.aggregation val lastAggregation = aggregationsAndBlobs.findLast { it.aggregation != null }!!.aggregation
@@ -318,8 +318,8 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
.isEqualTo( .isEqualTo(
StateRecoveryStatus( StateRecoveryStatus(
headBlockNumber = lastAggregation!!.endBlockNumber, headBlockNumber = lastAggregation!!.endBlockNumber,
stateRecoverStartBlockNumber = headBlockNumberAtStart + 1UL stateRecoverStartBlockNumber = headBlockNumberAtStart + 1UL,
) ),
) )
} }
// assert it does not try to import blocks behind the head block // assert it does not try to import blocks behind the head block
@@ -331,12 +331,12 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
fun `should stop recovery as soon as stateroot mismatches`() { fun `should stop recovery as soon as stateroot mismatches`() {
fakeStateManagerClient.setBlockStateRootHash( fakeStateManagerClient.setBlockStateRootHash(
aggregationsAndBlobs[1].aggregation!!.endBlockNumber, aggregationsAndBlobs[1].aggregation!!.endBlockNumber,
ByteArray(32) { 1 } ByteArray(32) { 1 },
) )
log.debug( log.debug(
"aggregations={} forcedMismatchAggregation={}", "aggregations={} forcedMismatchAggregation={}",
aggregationsAndBlobs.map { it.aggregation?.intervalString() }, aggregationsAndBlobs.map { it.aggregation?.intervalString() },
aggregationsAndBlobs[1].aggregation!!.intervalString() aggregationsAndBlobs[1].aggregation!!.intervalString(),
) )
val stateRecoverApp = instantiateStateRecoveryApp() val stateRecoverApp = instantiateStateRecoveryApp()
@@ -368,7 +368,7 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
log.debug( log.debug(
"headBlockNumber={} forceSyncStopBlockNumber={}", "headBlockNumber={} forceSyncStopBlockNumber={}",
fakeExecutionLayerClient.headBlock.number, fakeExecutionLayerClient.headBlock.number,
debugForceSyncStopBlockNumber debugForceSyncStopBlockNumber,
) )
assertThat(fakeExecutionLayerClient.headBlock.number).isGreaterThanOrEqualTo(debugForceSyncStopBlockNumber) assertThat(fakeExecutionLayerClient.headBlock.number).isGreaterThanOrEqualTo(debugForceSyncStopBlockNumber)
} }

View File

@@ -42,7 +42,7 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
private val testDataDir = "testdata/coordinator/prover/v3/stateRecovery" private val testDataDir = "testdata/coordinator/prover/v3/stateRecovery"
private val aggregationsAndBlobs: List<AggregationAndBlobs> = loadBlobsAndAggregationsSortedAndGrouped( private val aggregationsAndBlobs: List<AggregationAndBlobs> = loadBlobsAndAggregationsSortedAndGrouped(
blobsResponsesDir = "$testDataDir/compression/responses", blobsResponsesDir = "$testDataDir/compression/responses",
aggregationsResponsesDir = "$testDataDir/aggregation/responses" aggregationsResponsesDir = "$testDataDir/aggregation/responses",
) )
private lateinit var rollupDeploymentResult: LineaRollupDeploymentResult private lateinit var rollupDeploymentResult: LineaRollupDeploymentResult
private lateinit var contractClientForBlobSubmission: LineaRollupSmartContractClient private lateinit var contractClientForBlobSubmission: LineaRollupSmartContractClient
@@ -54,7 +54,7 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
fun beforeEach(vertx: Vertx) { fun beforeEach(vertx: Vertx) {
val jsonRpcFactory = VertxHttpJsonRpcClientFactory( val jsonRpcFactory = VertxHttpJsonRpcClientFactory(
vertx = vertx, vertx = vertx,
metricsFacade = MicrometerMetricsFacade(SimpleMeterRegistry()) metricsFacade = MicrometerMetricsFacade(SimpleMeterRegistry()),
) )
stateManagerClient = StateManagerV1JsonRpcClient.create( stateManagerClient = StateManagerV1JsonRpcClient.create(
@@ -63,10 +63,10 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
maxInflightRequestsPerClient = 1U, maxInflightRequestsPerClient = 1U,
requestRetry = RequestRetryConfig( requestRetry = RequestRetryConfig(
backoffDelay = 1.seconds, backoffDelay = 1.seconds,
timeout = 4.seconds timeout = 4.seconds,
), ),
zkStateManagerVersion = "2.3.0", zkStateManagerVersion = "2.3.0",
logger = LogManager.getLogger("test.clients.l1.state-manager") logger = LogManager.getLogger("test.clients.l1.state-manager"),
) )
configureLoggers( configureLoggers(
@@ -74,7 +74,7 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
log.name to Level.DEBUG, log.name to Level.DEBUG,
"net.consensys.linea.contract.Web3JContractAsyncHelper" to Level.WARN, // silence noisy gasPrice Caps logs "net.consensys.linea.contract.Web3JContractAsyncHelper" to Level.WARN, // silence noisy gasPrice Caps logs
"test.clients.l1.state-manager" to Level.DEBUG, "test.clients.l1.state-manager" to Level.DEBUG,
"test.clients.l1.web3j-default" to Level.DEBUG "test.clients.l1.web3j-default" to Level.DEBUG,
) )
} }
@@ -90,7 +90,7 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
rollupDeploymentResult.contractAddress, rollupDeploymentResult.contractAddress,
// index 0 is the first operator in rollupOperatorClient // index 0 is the first operator in rollupOperatorClient
rollupDeploymentResult.rollupOperators[1].txManager, rollupDeploymentResult.rollupOperators[1].txManager,
smartContractErrors = lineaRollupContractErrors smartContractErrors = lineaRollupContractErrors,
) )
log.info("starting stack for recovery of state pushed to L1") log.info("starting stack for recovery of state pushed to L1")
val staterecoveryNodesStartFuture = execCommandAndAssertSuccess( val staterecoveryNodesStartFuture = execCommandAndAssertSuccess(
@@ -98,7 +98,7 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
"L1_ROLLUP_CONTRACT_ADDRESS=${rollupDeploymentResult.contractAddress} " + "L1_ROLLUP_CONTRACT_ADDRESS=${rollupDeploymentResult.contractAddress} " +
"STATERECOVERY_OVERRIDE_START_BLOCK_NUMBER=1", "STATERECOVERY_OVERRIDE_START_BLOCK_NUMBER=1",
timeout = 1.minutes, timeout = 1.minutes,
log = log log = log,
).thenPeek { ).thenPeek {
log.info("make staterecovery-replay-from-block executed") log.info("make staterecovery-replay-from-block executed")
} }
@@ -114,7 +114,7 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
blobChunksMaxSize = 9, blobChunksMaxSize = 9,
l1Web3jClient = Web3jClientManager.l1Client, l1Web3jClient = Web3jClientManager.l1Client,
waitTimeout = 4.minutes, waitTimeout = 4.minutes,
log = log log = log,
) )
log.info("finalization={} executed on l1", lastAggregation.intervalString()) log.info("finalization={} executed on l1", lastAggregation.intervalString())
} }
@@ -125,13 +125,13 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
assertBesuAndShomeiRecoveredAsExpected( assertBesuAndShomeiRecoveredAsExpected(
lastAggregationAndBlobs, lastAggregationAndBlobs,
timeout = 5.minutes timeout = 5.minutes,
) )
} }
private fun assertBesuAndShomeiRecoveredAsExpected( private fun assertBesuAndShomeiRecoveredAsExpected(
targetAggregationAndBlobs: AggregationAndBlobs, targetAggregationAndBlobs: AggregationAndBlobs,
timeout: Duration timeout: Duration,
) { ) {
val targetAggregation = targetAggregationAndBlobs.aggregation!! val targetAggregation = targetAggregationAndBlobs.aggregation!!
val expectedZkEndStateRootHash = targetAggregationAndBlobs.blobs.last().blobCompressionProof!!.finalStateRootHash val expectedZkEndStateRootHash = targetAggregationAndBlobs.blobs.last().blobCompressionProof!!.finalStateRootHash
@@ -141,7 +141,7 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
stateManagerClient = stateManagerClient, stateManagerClient = stateManagerClient,
targetAggregation.endBlockNumber, targetAggregation.endBlockNumber,
expectedZkEndStateRootHash, expectedZkEndStateRootHash,
timeout = timeout timeout = timeout,
) )
} }
} }

View File

@@ -66,7 +66,7 @@ class SubmissionsFetchingTaskIntTest {
blobsResponsesDir = "$testDataDir/compression/responses", blobsResponsesDir = "$testDataDir/compression/responses",
aggregationsResponsesDir = "$testDataDir/aggregation/responses", aggregationsResponsesDir = "$testDataDir/aggregation/responses",
numberOfAggregations = 7, numberOfAggregations = 7,
extraBlobsWithoutAggregation = 0 extraBlobsWithoutAggregation = 0,
) )
val rollupDeploymentResult = ContractsManager.get() val rollupDeploymentResult = ContractsManager.get()
.deployLineaRollup(numberOfOperators = 2, contractVersion = LineaContractVersion.V6).get() .deployLineaRollup(numberOfOperators = 2, contractVersion = LineaContractVersion.V6).get()
@@ -77,14 +77,14 @@ class SubmissionsFetchingTaskIntTest {
l1RpcEndpoint = URI(l1RpcUrl), l1RpcEndpoint = URI(l1RpcUrl),
l1RequestRetryConfig = RetryConfig(backoffDelay = 2.seconds), l1RequestRetryConfig = RetryConfig(backoffDelay = 2.seconds),
blobScanEndpoint = URI(blobScanUrl), blobScanEndpoint = URI(blobScanUrl),
stateManagerClientEndpoint = URI("http://it-does-not-matter:5432") stateManagerClientEndpoint = URI("http://it-does-not-matter:5432"),
) )
contractClientForBlobSubmissions = rollupDeploymentResult.rollupOperatorClient contractClientForBlobSubmissions = rollupDeploymentResult.rollupOperatorClient
contractClientForAggregationSubmissions = connectToLineaRollupContract( contractClientForAggregationSubmissions = connectToLineaRollupContract(
rollupDeploymentResult.contractAddress, rollupDeploymentResult.contractAddress,
rollupDeploymentResult.rollupOperators[1].txManager, rollupDeploymentResult.rollupOperators[1].txManager,
smartContractErrors = lineaRollupContractErrors smartContractErrors = lineaRollupContractErrors,
) )
configureLoggers( configureLoggers(
rootLevel = Level.INFO, rootLevel = Level.INFO,
@@ -95,7 +95,7 @@ class SubmissionsFetchingTaskIntTest {
"linea.plugin.staterecovery.clients" to Level.DEBUG, "linea.plugin.staterecovery.clients" to Level.DEBUG,
"test.clients.l1.web3j-default" to Level.INFO, "test.clients.l1.web3j-default" to Level.INFO,
"test.clients.l1.web3j.receipt-poller" to Level.INFO, "test.clients.l1.web3j.receipt-poller" to Level.INFO,
"linea.staterecovery.datafetching" to Level.INFO "linea.staterecovery.datafetching" to Level.INFO,
) )
submitDataToL1ContactAndWaitExecution() submitDataToL1ContactAndWaitExecution()
} }
@@ -103,18 +103,18 @@ class SubmissionsFetchingTaskIntTest {
fun createFetcherTask( fun createFetcherTask(
l2StartBlockNumber: ULong, l2StartBlockNumber: ULong,
debugForceSyncStopBlockNumber: ULong? = null, debugForceSyncStopBlockNumber: ULong? = null,
queuesSizeLimit: Int = 2 queuesSizeLimit: Int = 2,
): SubmissionsFetchingTask { ): SubmissionsFetchingTask {
val l1EventsClient = LineaSubmissionEventsClientImpl( val l1EventsClient = LineaSubmissionEventsClientImpl(
logsSearcher = appClients.ethLogsSearcher, logsSearcher = appClients.ethLogsSearcher,
smartContractAddress = appClients.lineaContractClient.contractAddress, smartContractAddress = appClients.lineaContractClient.contractAddress,
l1LatestSearchBlock = BlockParameter.Tag.LATEST, l1LatestSearchBlock = BlockParameter.Tag.LATEST,
logsBlockChunkSize = 5000 logsBlockChunkSize = 5000,
) )
val blobDecompressor: BlobDecompressorAndDeserializer = BlobDecompressorToDomainV1( val blobDecompressor: BlobDecompressorAndDeserializer = BlobDecompressorToDomainV1(
decompressor = GoNativeBlobDecompressorFactory.getInstance(BlobDecompressorVersion.V1_2_0), decompressor = GoNativeBlobDecompressorFactory.getInstance(BlobDecompressorVersion.V1_2_0),
staticFields = BlockHeaderStaticFields.localDev, staticFields = BlockHeaderStaticFields.localDev,
vertx = vertx vertx = vertx,
) )
return SubmissionsFetchingTask( return SubmissionsFetchingTask(
@@ -129,14 +129,14 @@ class SubmissionsFetchingTaskIntTest {
submissionEventsQueueLimit = queuesSizeLimit, submissionEventsQueueLimit = queuesSizeLimit,
compressedBlobsQueueLimit = queuesSizeLimit, compressedBlobsQueueLimit = queuesSizeLimit,
targetDecompressedBlobsQueueLimit = queuesSizeLimit, targetDecompressedBlobsQueueLimit = queuesSizeLimit,
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber,
) )
} }
private fun submitDataToL1ContactAndWaitExecution( private fun submitDataToL1ContactAndWaitExecution(
aggregationsAndBlobs: List<AggregationAndBlobs> = this.aggregationsAndBlobs, aggregationsAndBlobs: List<AggregationAndBlobs> = this.aggregationsAndBlobs,
blobChunksSize: Int = 9, blobChunksSize: Int = 9,
waitTimeout: Duration = 4.minutes waitTimeout: Duration = 4.minutes,
) { ) {
submitBlobsAndAggregationsAndWaitExecution( submitBlobsAndAggregationsAndWaitExecution(
contractClientForBlobSubmission = contractClientForBlobSubmissions, contractClientForBlobSubmission = contractClientForBlobSubmissions,
@@ -146,9 +146,9 @@ class SubmissionsFetchingTaskIntTest {
waitTimeout = waitTimeout, waitTimeout = waitTimeout,
l1Web3jClient = createWeb3jHttpClient( l1Web3jClient = createWeb3jHttpClient(
rpcUrl = l1RpcUrl, rpcUrl = l1RpcUrl,
log = LogManager.getLogger("test.clients.l1.web3j.receipt-poller") log = LogManager.getLogger("test.clients.l1.web3j.receipt-poller"),
), ),
log = log log = log,
) )
} }
@@ -171,17 +171,17 @@ class SubmissionsFetchingTaskIntTest {
assertSubmissionsAreCorrectlyFetched( assertSubmissionsAreCorrectlyFetched(
l2StartBlockNumber = 1UL, l2StartBlockNumber = 1UL,
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber,
) )
} }
private fun assertSubmissionsAreCorrectlyFetched( private fun assertSubmissionsAreCorrectlyFetched(
l2StartBlockNumber: ULong, l2StartBlockNumber: ULong,
debugForceSyncStopBlockNumber: ULong? = null debugForceSyncStopBlockNumber: ULong? = null,
) { ) {
val submissionsFetcher = createFetcherTask( val submissionsFetcher = createFetcherTask(
l2StartBlockNumber = l2StartBlockNumber, l2StartBlockNumber = l2StartBlockNumber,
queuesSizeLimit = 2 queuesSizeLimit = 2,
) )
.also { it.start() } .also { it.start() }
val expectedAggregationsAndBlobsToBeFetched = val expectedAggregationsAndBlobsToBeFetched =
@@ -208,7 +208,7 @@ class SubmissionsFetchingTaskIntTest {
?.also { nextSubmission -> ?.also { nextSubmission ->
fetchedSubmissions.add(nextSubmission) fetchedSubmissions.add(nextSubmission)
submissionsFetcher.pruneQueueForElementsUpToInclusive( submissionsFetcher.pruneQueueForElementsUpToInclusive(
elHeadBlockNumber = nextSubmission.submissionEvents.dataFinalizedEvent.event.endBlockNumber elHeadBlockNumber = nextSubmission.submissionEvents.dataFinalizedEvent.event.endBlockNumber,
) )
} }
assertThat(submissionsFetcher.finalizationsReadyToImport()).isLessThanOrEqualTo(2) assertThat(submissionsFetcher.finalizationsReadyToImport()).isLessThanOrEqualTo(2)
@@ -241,11 +241,11 @@ class SubmissionsFetchingTaskIntTest {
fun assertFetchedData( fun assertFetchedData(
fetchedData: SubmissionEventsAndData<BlockFromL1RecoveredData>, fetchedData: SubmissionEventsAndData<BlockFromL1RecoveredData>,
sotAggregationData: AggregationAndBlobs sotAggregationData: AggregationAndBlobs,
) { ) {
assertEventMatchesAggregation( assertEventMatchesAggregation(
fetchedData.submissionEvents.dataFinalizedEvent.event, fetchedData.submissionEvents.dataFinalizedEvent.event,
sotAggregationData.aggregation!! sotAggregationData.aggregation!!,
) )
assertThat(fetchedData.data.first().header.blockNumber) assertThat(fetchedData.data.first().header.blockNumber)
.isEqualTo(sotAggregationData.blobs.first().startBlockNumber) .isEqualTo(sotAggregationData.blobs.first().startBlockNumber)
@@ -255,7 +255,7 @@ class SubmissionsFetchingTaskIntTest {
fun assertEventMatchesAggregation( fun assertEventMatchesAggregation(
event: DataFinalizedV3, event: DataFinalizedV3,
aggregation: Aggregation aggregation: Aggregation,
) { ) {
assertThat(event.startBlockNumber).isEqualTo(aggregation.startBlockNumber) assertThat(event.startBlockNumber).isEqualTo(aggregation.startBlockNumber)
assertThat(event.endBlockNumber).isEqualTo(aggregation.endBlockNumber) assertThat(event.endBlockNumber).isEqualTo(aggregation.endBlockNumber)

View File

@@ -12,7 +12,7 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture
class FakeExecutionLayerClient( class FakeExecutionLayerClient(
headBlock: BlockNumberAndHash = BlockNumberAndHash(number = 0uL, hash = ByteArray(32) { 0 }), headBlock: BlockNumberAndHash = BlockNumberAndHash(number = 0uL, hash = ByteArray(32) { 0 }),
initialStateRecoverStartBlockNumber: ULong? = null, initialStateRecoverStartBlockNumber: ULong? = null,
loggerName: String? = null loggerName: String? = null,
) : ExecutionLayerClient { ) : ExecutionLayerClient {
private val log = loggerName private val log = loggerName
?.let { LogManager.getLogger(loggerName) } ?.let { LogManager.getLogger(loggerName) }
@@ -35,7 +35,7 @@ class FakeExecutionLayerClient(
val stateRecoverStatus: StateRecoveryStatus val stateRecoverStatus: StateRecoveryStatus
get() = StateRecoveryStatus( get() = StateRecoveryStatus(
headBlockNumber = headBlock.number, headBlockNumber = headBlock.number,
stateRecoverStartBlockNumber = stateRecoverStartBlockNumber stateRecoverStartBlockNumber = stateRecoverStartBlockNumber,
) )
@Synchronized @Synchronized
@@ -46,14 +46,14 @@ class FakeExecutionLayerClient(
@Synchronized @Synchronized
override fun lineaEngineImportBlocksFromBlob( override fun lineaEngineImportBlocksFromBlob(
blocks: List<BlockFromL1RecoveredData> blocks: List<BlockFromL1RecoveredData>,
): SafeFuture<Unit> { ): SafeFuture<Unit> {
if (log.isTraceEnabled) { if (log.isTraceEnabled) {
log.trace("lineaEngineImportBlocksFromBlob($blocks)") log.trace("lineaEngineImportBlocksFromBlob($blocks)")
} else { } else {
val interval = CommonDomainFunctions.blockIntervalString( val interval = CommonDomainFunctions.blockIntervalString(
blocks.first().header.blockNumber, blocks.first().header.blockNumber,
blocks.last().header.blockNumber blocks.last().header.blockNumber,
) )
log.debug("lineaEngineImportBlocksFromBlob(interval=$interval)") log.debug("lineaEngineImportBlocksFromBlob(interval=$interval)")
} }
@@ -64,7 +64,7 @@ class FakeExecutionLayerClient(
@Synchronized @Synchronized
override fun getBlockNumberAndHash( override fun getBlockNumberAndHash(
blockParameter: BlockParameter blockParameter: BlockParameter,
): SafeFuture<BlockNumberAndHash> { ): SafeFuture<BlockNumberAndHash> {
log.trace("getBlockNumberAndHash($blockParameter): $headBlock") log.trace("getBlockNumberAndHash($blockParameter): $headBlock")
return SafeFuture.completedFuture(headBlock) return SafeFuture.completedFuture(headBlock)
@@ -78,7 +78,7 @@ class FakeExecutionLayerClient(
@Synchronized @Synchronized
override fun lineaEnableStateRecovery( override fun lineaEnableStateRecovery(
stateRecoverStartBlockNumber: ULong stateRecoverStartBlockNumber: ULong,
): SafeFuture<StateRecoveryStatus> { ): SafeFuture<StateRecoveryStatus> {
this.stateRecoverStartBlockNumber = stateRecoverStartBlockNumber this.stateRecoverStartBlockNumber = stateRecoverStartBlockNumber
log.debug("lineaEnableStateRecovery($stateRecoverStartBlockNumber) = $stateRecoverStatus") log.debug("lineaEnableStateRecovery($stateRecoverStartBlockNumber) = $stateRecoverStatus")

View File

@@ -18,7 +18,7 @@ import java.util.concurrent.ConcurrentHashMap
open class FakeStateManagerClient( open class FakeStateManagerClient(
_blocksStateRootHashes: Map<ULong, ByteArray> = emptyMap(), _blocksStateRootHashes: Map<ULong, ByteArray> = emptyMap(),
var headBlockNumber: ULong = _blocksStateRootHashes.keys.maxOrNull() ?: 0UL var headBlockNumber: ULong = _blocksStateRootHashes.keys.maxOrNull() ?: 0UL,
) : StateManagerClientV1 { ) : StateManagerClientV1 {
open val blocksStateRootHashes: MutableMap<ULong, ByteArray> = open val blocksStateRootHashes: MutableMap<ULong, ByteArray> =
ConcurrentHashMap<ULong, ByteArray>(_blocksStateRootHashes) ConcurrentHashMap<ULong, ByteArray>(_blocksStateRootHashes)
@@ -33,8 +33,8 @@ open class FakeStateManagerClient(
?.let { SafeFuture.completedFuture(it) } ?.let { SafeFuture.completedFuture(it) }
?: SafeFuture.failedFuture( ?: SafeFuture.failedFuture(
RuntimeException( RuntimeException(
"StateRootHash not found for block=$blockNumber. available blocks: ${blocksStateRootHashes.keys}" "StateRootHash not found for block=$blockNumber. available blocks: ${blocksStateRootHashes.keys}",
) ),
) )
} }
@@ -43,7 +43,7 @@ open class FakeStateManagerClient(
} }
override fun rollupGetStateMerkleProofWithTypedError( override fun rollupGetStateMerkleProofWithTypedError(
blockInterval: BlockInterval blockInterval: BlockInterval,
): SafeFuture<Result<GetZkEVMStateMerkleProofResponse, ErrorResponse<StateManagerErrorType>>> { ): SafeFuture<Result<GetZkEVMStateMerkleProofResponse, ErrorResponse<StateManagerErrorType>>> {
// For state recovery, we just need the endStateRootHash // For state recovery, we just need the endStateRootHash
return getStateRootHash(blockInterval.endBlockNumber) return getStateRootHash(blockInterval.endBlockNumber)
@@ -53,26 +53,26 @@ open class FakeStateManagerClient(
zkStateMerkleProof = ArrayNode(null), zkStateMerkleProof = ArrayNode(null),
zkParentStateRootHash = ByteArray(32), zkParentStateRootHash = ByteArray(32),
zkEndStateRootHash = stateRootHash, zkEndStateRootHash = stateRootHash,
zkStateManagerVersion = "fake-version" zkStateManagerVersion = "fake-version",
) ),
) )
} }
} }
} }
class FakeStateManagerClientBasedOnBlobsRecords( class FakeStateManagerClientBasedOnBlobsRecords(
val blobRecords: List<BlobRecord> val blobRecords: List<BlobRecord>,
) : FakeStateManagerClient( ) : FakeStateManagerClient(
_blocksStateRootHashes = blobRecords _blocksStateRootHashes = blobRecords
.associate { it.endBlockNumber to it.blobCompressionProof!!.finalStateRootHash } .associate { it.endBlockNumber to it.blobCompressionProof!!.finalStateRootHash },
) )
class FakeStateManagerClientReadFromL1( class FakeStateManagerClientReadFromL1(
headBlockNumber: ULong, headBlockNumber: ULong,
val logsSearcher: EthLogsSearcher, val logsSearcher: EthLogsSearcher,
val contractAddress: String val contractAddress: String,
) : FakeStateManagerClient( ) : FakeStateManagerClient(
headBlockNumber = headBlockNumber headBlockNumber = headBlockNumber,
) { ) {
override fun getStateRootHash(blockNumber: ULong): SafeFuture<ByteArray> { override fun getStateRootHash(blockNumber: ULong): SafeFuture<ByteArray> {
@@ -87,8 +87,8 @@ class FakeStateManagerClientReadFromL1(
topics = listOf( topics = listOf(
DataFinalizedV3.topic, DataFinalizedV3.topic,
null, null,
blockNumber.toHexStringUInt256() blockNumber.toHexStringUInt256(),
) ),
).thenApply { logs -> ).thenApply { logs ->
logs.firstOrNull()?.let { finalizationLog -> logs.firstOrNull()?.let { finalizationLog ->
DataFinalizedV3.fromEthLog(finalizationLog).event.finalStateRootHash DataFinalizedV3.fromEthLog(finalizationLog).event.finalStateRootHash

View File

@@ -34,7 +34,7 @@ open class TestRunner(
private val l1RpcUrl: String, private val l1RpcUrl: String,
private val blobScanUrl: String, private val blobScanUrl: String,
private val blobScanRatelimitBackoffDelay: Duration? = 1.seconds, private val blobScanRatelimitBackoffDelay: Duration? = 1.seconds,
private val debugForceSyncStopBlockNumber: ULong = ULong.MAX_VALUE private val debugForceSyncStopBlockNumber: ULong = ULong.MAX_VALUE,
) { ) {
private val log = LogManager.getLogger("test.case.TestRunner") private val log = LogManager.getLogger("test.case.TestRunner")
val appConfig = StateRecoveryApp.Config( val appConfig = StateRecoveryApp.Config(
@@ -45,7 +45,7 @@ open class TestRunner(
executionClientPollingInterval = 1.seconds, executionClientPollingInterval = 1.seconds,
smartContractAddress = smartContractAddress, smartContractAddress = smartContractAddress,
l1getLogsChunkSize = 10_000u, l1getLogsChunkSize = 10_000u,
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber,
) )
val appClients = createAppClients( val appClients = createAppClients(
vertx = vertx, vertx = vertx,
@@ -56,17 +56,17 @@ open class TestRunner(
blobScanEndpoint = URI(blobScanUrl), blobScanEndpoint = URI(blobScanUrl),
blobScanRequestRetryConfig = RetryConfig(backoffDelay = 10.milliseconds, timeout = 2.minutes), blobScanRequestRetryConfig = RetryConfig(backoffDelay = 10.milliseconds, timeout = 2.minutes),
blobscanRequestRateLimitBackoffDelay = blobScanRatelimitBackoffDelay, blobscanRequestRateLimitBackoffDelay = blobScanRatelimitBackoffDelay,
stateManagerClientEndpoint = URI("http://it-does-not-matter:5432") stateManagerClientEndpoint = URI("http://it-does-not-matter:5432"),
) )
private val fakeExecutionLayerClient = FakeExecutionLayerClient( private val fakeExecutionLayerClient = FakeExecutionLayerClient(
headBlock = BlockNumberAndHash(number = l2RecoveryStartBlockNumber - 1UL, hash = ByteArray(32) { 0 }), headBlock = BlockNumberAndHash(number = l2RecoveryStartBlockNumber - 1UL, hash = ByteArray(32) { 0 }),
initialStateRecoverStartBlockNumber = l2RecoveryStartBlockNumber, initialStateRecoverStartBlockNumber = l2RecoveryStartBlockNumber,
loggerName = "test.fake.clients.execution-layer" loggerName = "test.fake.clients.execution-layer",
) )
var fakeStateManagerClient: StateManagerClientV1 = FakeStateManagerClientReadFromL1( var fakeStateManagerClient: StateManagerClientV1 = FakeStateManagerClientReadFromL1(
headBlockNumber = ULong.MAX_VALUE, headBlockNumber = ULong.MAX_VALUE,
logsSearcher = appClients.ethLogsSearcher, logsSearcher = appClients.ethLogsSearcher,
contractAddress = StateRecoveryApp.Config.lineaSepolia.smartContractAddress contractAddress = StateRecoveryApp.Config.lineaSepolia.smartContractAddress,
) )
var stateRecoverApp: StateRecoveryApp = StateRecoveryApp( var stateRecoverApp: StateRecoveryApp = StateRecoveryApp(
vertx = vertx, vertx = vertx,
@@ -77,7 +77,7 @@ open class TestRunner(
transactionDetailsClient = appClients.transactionDetailsClient, transactionDetailsClient = appClients.transactionDetailsClient,
blockHeaderStaticFields = BlockHeaderStaticFields.localDev, blockHeaderStaticFields = BlockHeaderStaticFields.localDev,
lineaContractClient = appClients.lineaContractClient, lineaContractClient = appClients.lineaContractClient,
config = appConfig config = appConfig,
) )
init { init {
@@ -86,12 +86,12 @@ open class TestRunner(
"linea.staterecovery" to Level.TRACE, "linea.staterecovery" to Level.TRACE,
"linea.plugin.staterecovery" to Level.INFO, "linea.plugin.staterecovery" to Level.INFO,
"linea.plugin.staterecovery.clients.l1.blob-scan" to Level.TRACE, "linea.plugin.staterecovery.clients.l1.blob-scan" to Level.TRACE,
"linea.plugin.staterecovery.clients.l1.logs-searcher" to Level.INFO "linea.plugin.staterecovery.clients.l1.logs-searcher" to Level.INFO,
) )
} }
fun run( fun run(
timeout: kotlin.time.Duration = 10.minutes timeout: kotlin.time.Duration = 10.minutes,
) { ) {
log.info("Running test case") log.info("Running test case")
stateRecoverApp.start().get() stateRecoverApp.start().get()
@@ -113,7 +113,7 @@ fun main() {
l2RecoveryStartBlockNumber = 18_504_528UL, l2RecoveryStartBlockNumber = 18_504_528UL,
l1RpcUrl = "https://mainnet.infura.io/v3/$infuraAppKey", l1RpcUrl = "https://mainnet.infura.io/v3/$infuraAppKey",
blobScanUrl = "https://api.blobscan.com/", blobScanUrl = "https://api.blobscan.com/",
blobScanRatelimitBackoffDelay = 1.seconds blobScanRatelimitBackoffDelay = 1.seconds,
) )
// val sepoliaTestRunner = TestRunner( // val sepoliaTestRunner = TestRunner(
// l1RpcUrl = "https://sepolia.infura.io/v3/$infuraAppKey", // l1RpcUrl = "https://sepolia.infura.io/v3/$infuraAppKey",

View File

@@ -19,7 +19,7 @@ import kotlin.time.toJavaDuration
fun execCommandAndAssertSuccess( fun execCommandAndAssertSuccess(
command: String, command: String,
timeout: Duration = 1.minutes, timeout: Duration = 1.minutes,
log: Logger log: Logger,
): SafeFuture<CommandResult> { ): SafeFuture<CommandResult> {
return Runner return Runner
.executeCommandFailOnNonZeroExitCode(command, timeout = timeout, log = log) .executeCommandFailOnNonZeroExitCode(command, timeout = timeout, log = log)
@@ -35,7 +35,7 @@ fun assertBesuAndShomeiRecoveredAsExpected(
stateManagerClient: StateManagerClientV1, stateManagerClient: StateManagerClientV1,
expectedBlockNumber: ULong, expectedBlockNumber: ULong,
expectedZkEndStateRootHash: ByteArray, expectedZkEndStateRootHash: ByteArray,
timeout: Duration = 60.seconds timeout: Duration = 60.seconds,
) { ) {
await() await()
.pollInterval(1.seconds.toJavaDuration()) .pollInterval(1.seconds.toJavaDuration())
@@ -53,7 +53,7 @@ fun waitExecutionLayerToBeUpAndRunning(
executionLayerUrl: String, executionLayerUrl: String,
expectedHeadBlockNumber: ULong = 0UL, expectedHeadBlockNumber: ULong = 0UL,
log: Logger, log: Logger,
timeout: Duration = 2.minutes timeout: Duration = 2.minutes,
) { ) {
val web3jElClient = createWeb3jHttpClient(executionLayerUrl) val web3jElClient = createWeb3jHttpClient(executionLayerUrl)
await() await()

View File

@@ -7,7 +7,7 @@ import linea.staterecovery.DataFinalizedV3
fun getLastFinalizationOnL1( fun getLastFinalizationOnL1(
logsSearcher: EthLogsSearcherImpl, logsSearcher: EthLogsSearcherImpl,
contractAddress: String contractAddress: String,
): EthLogEvent<DataFinalizedV3> { ): EthLogEvent<DataFinalizedV3> {
return getFinalizationsOnL1(logsSearcher, contractAddress) return getFinalizationsOnL1(logsSearcher, contractAddress)
.lastOrNull() .lastOrNull()
@@ -16,12 +16,12 @@ fun getLastFinalizationOnL1(
fun getFinalizationsOnL1( fun getFinalizationsOnL1(
logsSearcher: EthLogsSearcherImpl, logsSearcher: EthLogsSearcherImpl,
contractAddress: String contractAddress: String,
): List<EthLogEvent<DataFinalizedV3>> { ): List<EthLogEvent<DataFinalizedV3>> {
return logsSearcher.getLogs( return logsSearcher.getLogs(
fromBlock = BlockParameter.Tag.EARLIEST, fromBlock = BlockParameter.Tag.EARLIEST,
toBlock = BlockParameter.Tag.LATEST, toBlock = BlockParameter.Tag.LATEST,
address = contractAddress, address = contractAddress,
topics = listOf(DataFinalizedV3.topic) topics = listOf(DataFinalizedV3.topic),
).get().map(DataFinalizedV3.Companion::fromEthLog) ).get().map(DataFinalizedV3.Companion::fromEthLog)
} }

View File

@@ -118,18 +118,13 @@ allprojects {
indentWithSpaces(2) indentWithSpaces(2)
endWithNewline() endWithNewline()
} }
}
// TODO in later ticket - apply these linting rules to all monorepo projects java {
if (subproject.path.startsWith(':besu-plugins:linea-sequencer')) { target 'src/**/*.java'
subproject.spotless { targetExclude '**/src/test/java/**ReferenceTest**', '**/src/main/generated/**', '**/src/test/generated/**', '**/src/jmh/generated/**'
java { removeUnusedImports()
target 'src/**/*.java' trimTrailingWhitespace()
targetExclude '**/src/test/java/**ReferenceTest**', '**/src/main/generated/**', '**/src/test/generated/**', '**/src/jmh/generated/**' endWithNewline()
removeUnusedImports()
trimTrailingWhitespace()
endWithNewline()
}
} }
} }
} }

View File

@@ -19,7 +19,7 @@ import org.apache.logging.log4j.Logger
import java.nio.file.Path import java.nio.file.Path
inline fun <reified T : Any> loadConfigsOrError( inline fun <reified T : Any> loadConfigsOrError(
configFiles: List<Path> configFiles: List<Path>,
): Result<T, String> { ): Result<T, String> {
val confBuilder: ConfigLoaderBuilder = ConfigLoaderBuilder.Companion val confBuilder: ConfigLoaderBuilder = ConfigLoaderBuilder.Companion
.empty() .empty()
@@ -43,7 +43,7 @@ fun logErrorIfPresent(
configName: String, configName: String,
configFiles: List<Path>, configFiles: List<Path>,
configLoadingResult: Result<Any?, String>, configLoadingResult: Result<Any?, String>,
logger: Logger logger: Logger,
) { ) {
if (configLoadingResult is Err) { if (configLoadingResult is Err) {
logger.error("Failed to load $configName from files=$configFiles with error=${configLoadingResult.error}") logger.error("Failed to load $configName from files=$configFiles with error=${configLoadingResult.error}")
@@ -53,7 +53,7 @@ fun logErrorIfPresent(
inline fun <reified T : Any> loadConfigsAndLogErrors( inline fun <reified T : Any> loadConfigsAndLogErrors(
configFiles: List<Path>, configFiles: List<Path>,
configName: String, configName: String,
logger: Logger = LogManager.getLogger("linea.coordinator.config") logger: Logger = LogManager.getLogger("linea.coordinator.config"),
): Result<T, String> { ): Result<T, String> {
return loadConfigsOrError<T>(configFiles) return loadConfigsOrError<T>(configFiles)
.also { logErrorIfPresent(configName, configFiles, it, logger) } .also { logErrorIfPresent(configName, configFiles, it, logger) }
@@ -64,7 +64,7 @@ fun loadConfigsOrError(
tracesLimitsFileV2: Path, tracesLimitsFileV2: Path,
gasPriceCapTimeOfDayMultipliersFile: Path, gasPriceCapTimeOfDayMultipliersFile: Path,
smartContractErrorsFile: Path, smartContractErrorsFile: Path,
logger: Logger = LogManager.getLogger("linea.coordinator.config") logger: Logger = LogManager.getLogger("linea.coordinator.config"),
): Result<CoordinatorConfigTomlDto, String> { ): Result<CoordinatorConfigTomlDto, String> {
val coordinatorBaseConfigs = val coordinatorBaseConfigs =
loadConfigsAndLogErrors<CoordinatorConfigTomlDto>(coordinatorConfigFiles, "coordinator", logger) loadConfigsAndLogErrors<CoordinatorConfigTomlDto>(coordinatorConfigFiles, "coordinator", logger)
@@ -74,18 +74,18 @@ fun loadConfigsOrError(
loadConfigsAndLogErrors<GasPriceCapTimeOfDayMultipliersConfig>( loadConfigsAndLogErrors<GasPriceCapTimeOfDayMultipliersConfig>(
listOf(gasPriceCapTimeOfDayMultipliersFile), listOf(gasPriceCapTimeOfDayMultipliersFile),
"l1 submission gas prices caps", "l1 submission gas prices caps",
logger logger,
) )
val smartContractErrorsConfig = loadConfigsAndLogErrors<SmartContractErrorCodesConfig>( val smartContractErrorsConfig = loadConfigsAndLogErrors<SmartContractErrorCodesConfig>(
listOf(smartContractErrorsFile), listOf(smartContractErrorsFile),
"smart contract errors", "smart contract errors",
logger logger,
) )
val configError = listOf( val configError = listOf(
coordinatorBaseConfigs, coordinatorBaseConfigs,
tracesLimitsV2Configs, tracesLimitsV2Configs,
gasPriceCapTimeOfDayMultipliersConfig, gasPriceCapTimeOfDayMultipliersConfig,
smartContractErrorsConfig smartContractErrorsConfig,
) )
.find { it is Err } .find { it is Err }
@@ -98,13 +98,13 @@ fun loadConfigsOrError(
val finalConfig = baseConfig.copy( val finalConfig = baseConfig.copy(
conflation = baseConfig.conflation.copy( conflation = baseConfig.conflation.copy(
_tracesLimitsV2 = tracesLimitsV2Configs.get()?.tracesLimits?.let { TracesCountersV2(it) }, _tracesLimitsV2 = tracesLimitsV2Configs.get()?.tracesLimits?.let { TracesCountersV2(it) },
_smartContractErrors = smartContractErrorsConfig.get()!!.smartContractErrors _smartContractErrors = smartContractErrorsConfig.get()!!.smartContractErrors,
), ),
l1DynamicGasPriceCapService = baseConfig.l1DynamicGasPriceCapService.copy( l1DynamicGasPriceCapService = baseConfig.l1DynamicGasPriceCapService.copy(
gasPriceCapCalculation = baseConfig.l1DynamicGasPriceCapService.gasPriceCapCalculation.copy( gasPriceCapCalculation = baseConfig.l1DynamicGasPriceCapService.gasPriceCapCalculation.copy(
timeOfDayMultipliers = gasPriceCapTimeOfDayMultipliersConfig.get()?.gasPriceCapTimeOfDayMultipliers timeOfDayMultipliers = gasPriceCapTimeOfDayMultipliersConfig.get()?.gasPriceCapTimeOfDayMultipliers,
) ),
) ),
) )
return Ok(finalConfig) return Ok(finalConfig)
} }
@@ -114,14 +114,14 @@ fun loadConfigs(
tracesLimitsFileV2: Path, tracesLimitsFileV2: Path,
gasPriceCapTimeOfDayMultipliersFile: Path, gasPriceCapTimeOfDayMultipliersFile: Path,
smartContractErrorsFile: Path, smartContractErrorsFile: Path,
logger: Logger = LogManager.getLogger("linea.coordinator.config") logger: Logger = LogManager.getLogger("linea.coordinator.config"),
): CoordinatorConfig { ): CoordinatorConfig {
loadConfigsOrError( loadConfigsOrError(
coordinatorConfigFiles, coordinatorConfigFiles,
tracesLimitsFileV2, tracesLimitsFileV2,
gasPriceCapTimeOfDayMultipliersFile, gasPriceCapTimeOfDayMultipliersFile,
smartContractErrorsFile, smartContractErrorsFile,
logger logger,
).let { ).let {
return it return it
.getOrElse { .getOrElse {

View File

@@ -6,10 +6,10 @@ import net.consensys.linea.vertx.ObservabilityServer
class Api( class Api(
private val configs: Config, private val configs: Config,
private val vertx: Vertx private val vertx: Vertx,
) { ) {
data class Config( data class Config(
val observabilityPort: UInt val observabilityPort: UInt,
) )
private var observabilityServerId: String? = null private var observabilityServerId: String? = null

View File

@@ -23,7 +23,7 @@ import java.net.URI
fun createTransactionManager( fun createTransactionManager(
vertx: Vertx, vertx: Vertx,
signerConfig: SignerConfig, signerConfig: SignerConfig,
client: Web3j client: Web3j,
): AsyncFriendlyTransactionManager { ): AsyncFriendlyTransactionManager {
val transactionSignService = when (signerConfig.type) { val transactionSignService = when (signerConfig.type) {
SignerConfig.Type.Web3j -> { SignerConfig.Type.Web3j -> {
@@ -57,7 +57,7 @@ fun createLineaRollupContractClient(
contractGasProvider: ContractGasProvider, contractGasProvider: ContractGasProvider,
web3jClient: Web3j, web3jClient: Web3j,
smartContractErrors: SmartContractErrors, smartContractErrors: SmartContractErrors,
useEthEstimateGas: Boolean useEthEstimateGas: Boolean,
): LineaRollupSmartContractClient { ): LineaRollupSmartContractClient {
return Web3JLineaRollupSmartContractClient.load( return Web3JLineaRollupSmartContractClient.load(
contractAddress = l1Config.zkEvmContractAddress, contractAddress = l1Config.zkEvmContractAddress,
@@ -65,6 +65,6 @@ fun createLineaRollupContractClient(
transactionManager = transactionManager, transactionManager = transactionManager,
contractGasProvider = contractGasProvider, contractGasProvider = contractGasProvider,
smartContractErrors = smartContractErrors, smartContractErrors = smartContractErrors,
useEthEstimateGas = useEthEstimateGas useEthEstimateGas = useEthEstimateGas,
) )
} }

View File

@@ -51,20 +51,20 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
vertx = vertx, vertx = vertx,
metricsFacade = MicrometerMetricsFacade(meterRegistry), metricsFacade = MicrometerMetricsFacade(meterRegistry),
requestResponseLogLevel = Level.TRACE, requestResponseLogLevel = Level.TRACE,
failuresLogLevel = Level.WARN failuresLogLevel = Level.WARN,
) )
private val api = Api( private val api = Api(
Api.Config( Api.Config(
configs.api.observabilityPort configs.api.observabilityPort,
), ),
vertx vertx,
) )
private val l2Web3jClient: Web3j = createWeb3jHttpClient( private val l2Web3jClient: Web3j = createWeb3jHttpClient(
rpcUrl = configs.l2.rpcEndpoint.toString(), rpcUrl = configs.l2.rpcEndpoint.toString(),
log = LogManager.getLogger("clients.l2.eth-api.rpc-node"), log = LogManager.getLogger("clients.l2.eth-api.rpc-node"),
pollingInterval = 1.seconds, pollingInterval = 1.seconds,
requestResponseLogLevel = Level.TRACE, requestResponseLogLevel = Level.TRACE,
failuresLogLevel = Level.DEBUG failuresLogLevel = Level.DEBUG,
) )
private val persistenceRetryer = PersistenceRetryer( private val persistenceRetryer = PersistenceRetryer(
@@ -72,8 +72,8 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
config = PersistenceRetryer.Config( config = PersistenceRetryer.Config(
backoffDelay = configs.persistenceRetry.backoffDelay.toKotlinDuration(), backoffDelay = configs.persistenceRetry.backoffDelay.toKotlinDuration(),
maxRetries = configs.persistenceRetry.maxRetries, maxRetries = configs.persistenceRetry.maxRetries,
timeout = configs.persistenceRetry.timeout?.toKotlinDuration() timeout = configs.persistenceRetry.timeout?.toKotlinDuration(),
) ),
) )
private val sqlClient: SqlClient = initDb(configs.database) private val sqlClient: SqlClient = initDb(configs.database)
@@ -81,10 +81,10 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
PostgresBatchesRepository( PostgresBatchesRepository(
batchesDao = RetryingBatchesPostgresDao( batchesDao = RetryingBatchesPostgresDao(
delegate = BatchesPostgresDao( delegate = BatchesPostgresDao(
connection = sqlClient connection = sqlClient,
), ),
persistenceRetryer = persistenceRetryer persistenceRetryer = persistenceRetryer,
) ),
) )
private val blobsRepository = private val blobsRepository =
@@ -92,21 +92,21 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
blobsDao = RetryingBlobsPostgresDao( blobsDao = RetryingBlobsPostgresDao(
delegate = BlobsPostgresDao( delegate = BlobsPostgresDao(
config = BlobsPostgresDao.Config( config = BlobsPostgresDao.Config(
maxBlobsToReturn = configs.blobSubmission.maxBlobsToReturn.toUInt() maxBlobsToReturn = configs.blobSubmission.maxBlobsToReturn.toUInt(),
), ),
connection = sqlClient connection = sqlClient,
), ),
persistenceRetryer = persistenceRetryer persistenceRetryer = persistenceRetryer,
) ),
) )
private val aggregationsRepository = AggregationsRepositoryImpl( private val aggregationsRepository = AggregationsRepositoryImpl(
aggregationsPostgresDao = RetryingPostgresAggregationsDao( aggregationsPostgresDao = RetryingPostgresAggregationsDao(
delegate = PostgresAggregationsDao( delegate = PostgresAggregationsDao(
connection = sqlClient connection = sqlClient,
), ),
persistenceRetryer = persistenceRetryer persistenceRetryer = persistenceRetryer,
) ),
) )
private val l1FeeHistoriesRepository = private val l1FeeHistoriesRepository =
@@ -116,11 +116,11 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
minBaseFeePerBlobGasToCache = minBaseFeePerBlobGasToCache =
configs.l1DynamicGasPriceCapService.gasPriceCapCalculation.historicBaseFeePerBlobGasLowerBound, configs.l1DynamicGasPriceCapService.gasPriceCapCalculation.historicBaseFeePerBlobGasLowerBound,
fixedAverageRewardToCache = fixedAverageRewardToCache =
configs.l1DynamicGasPriceCapService.gasPriceCapCalculation.historicAvgRewardConstant configs.l1DynamicGasPriceCapService.gasPriceCapCalculation.historicAvgRewardConstant,
), ),
FeeHistoriesPostgresDao( FeeHistoriesPostgresDao(
sqlClient sqlClient,
) ),
) )
private val l1App = L1DependentApp( private val l1App = L1DependentApp(
@@ -133,7 +133,7 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
aggregationsRepository = aggregationsRepository, aggregationsRepository = aggregationsRepository,
l1FeeHistoriesRepository = l1FeeHistoriesRepository, l1FeeHistoriesRepository = l1FeeHistoriesRepository,
smartContractErrors = configs.conflation.smartContractErrors, smartContractErrors = configs.conflation.smartContractErrors,
metricsFacade = micrometerMetricsFacade metricsFacade = micrometerMetricsFacade,
) )
private val requestFileCleanup = DirectoryCleaner( private val requestFileCleanup = DirectoryCleaner(
@@ -144,7 +144,7 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
configs.proversConfig.proverA.proofAggregation.requestsDirectory, configs.proversConfig.proverA.proofAggregation.requestsDirectory,
configs.proversConfig.proverB?.execution?.requestsDirectory, configs.proversConfig.proverB?.execution?.requestsDirectory,
configs.proversConfig.proverB?.blobCompression?.requestsDirectory, configs.proversConfig.proverB?.blobCompression?.requestsDirectory,
configs.proversConfig.proverB?.proofAggregation?.requestsDirectory configs.proversConfig.proverB?.proofAggregation?.requestsDirectory,
), ),
fileFilters = DirectoryCleaner.getSuffixFileFilters( fileFilters = DirectoryCleaner.getSuffixFileFilters(
listOfNotNull( listOfNotNull(
@@ -153,9 +153,9 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
configs.proversConfig.proverA.proofAggregation.inprogressRequestWritingSuffix, configs.proversConfig.proverA.proofAggregation.inprogressRequestWritingSuffix,
configs.proversConfig.proverB?.execution?.inprogressRequestWritingSuffix, configs.proversConfig.proverB?.execution?.inprogressRequestWritingSuffix,
configs.proversConfig.proverB?.blobCompression?.inprogressRequestWritingSuffix, configs.proversConfig.proverB?.blobCompression?.inprogressRequestWritingSuffix,
configs.proversConfig.proverB?.proofAggregation?.inprogressRequestWritingSuffix configs.proversConfig.proverB?.proofAggregation?.inprogressRequestWritingSuffix,
) ),
) + DirectoryCleaner.JSON_FILE_FILTER ) + DirectoryCleaner.JSON_FILE_FILTER,
) )
init { init {
@@ -176,7 +176,7 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
SafeFuture.allOf( SafeFuture.allOf(
l1App.stop(), l1App.stop(),
SafeFuture.fromRunnable { l2Web3jClient.shutdown() }, SafeFuture.fromRunnable { l2Web3jClient.shutdown() },
api.stop().toSafeFuture() api.stop().toSafeFuture(),
).thenApply { ).thenApply {
LoadBalancingJsonRpcClient.stop() LoadBalancingJsonRpcClient.stop()
}.thenCompose { }.thenCompose {
@@ -201,7 +201,7 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
database = dbConfig.schema, database = dbConfig.schema,
target = dbVersion, target = dbVersion,
username = dbConfig.username, username = dbConfig.username,
password = dbConfig.password.value password = dbConfig.password.value,
) )
return Db.vertxSqlClient( return Db.vertxSqlClient(
vertx = vertx, vertx = vertx,
@@ -211,7 +211,7 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
username = dbConfig.username, username = dbConfig.username,
password = dbConfig.password.value, password = dbConfig.password.value,
maxPoolSize = dbConfig.transactionalPoolSize, maxPoolSize = dbConfig.transactionalPoolSize,
pipeliningLimit = dbConfig.readPipeliningLimit pipeliningLimit = dbConfig.readPipeliningLimit,
) )
} }
} }

View File

@@ -20,7 +20,7 @@ import java.util.concurrent.Callable
synopsisHeading = "%n", synopsisHeading = "%n",
descriptionHeading = "%nDescription:%n%n", descriptionHeading = "%nDescription:%n%n",
optionListHeading = "%nOptions:%n", optionListHeading = "%nOptions:%n",
footerHeading = "%n" footerHeading = "%n",
) )
class CoordinatorAppCli class CoordinatorAppCli
internal constructor(private val errorWriter: PrintWriter, private val startAction: StartAction) : internal constructor(private val errorWriter: PrintWriter, private val startAction: StartAction) :
@@ -32,7 +32,7 @@ internal constructor(private val errorWriter: PrintWriter, private val startActi
names = ["--traces-limits-v2"], names = ["--traces-limits-v2"],
paramLabel = "<FILE>", paramLabel = "<FILE>",
description = ["Prover traces limits for linea besu"], description = ["Prover traces limits for linea besu"],
arity = "1" arity = "1",
) )
private val tracesLimitsV2File: File? = null private val tracesLimitsV2File: File? = null
@@ -40,27 +40,24 @@ internal constructor(private val errorWriter: PrintWriter, private val startActi
names = ["--smart-contract-errors"], names = ["--smart-contract-errors"],
paramLabel = "<FILE>", paramLabel = "<FILE>",
description = ["Smart contract error codes"], description = ["Smart contract error codes"],
arity = "1" arity = "1",
) )
private val smartContractErrorsFile: File? = null private val smartContractErrorsFile: File? = null
@CommandLine.Option( @CommandLine.Option(
names = ["--gas-price-cap-time-of-day-multipliers"], names = ["--gas-price-cap-time-of-day-multipliers"],
paramLabel = "<FILE>", paramLabel = "<FILE>",
description = ["Time-of-day multipliers for calculation of L1 dynamic gas price caps"], description = ["Time-of-day multipliers for calculation of L1 dynamic gas price caps"],
arity = "1" arity = "1",
) )
private val gasPriceCapTimeOfDayMultipliersFile: File? = null private val gasPriceCapTimeOfDayMultipliersFile: File? = null
@CommandLine.Option( @CommandLine.Option(
names = ["--check-configs-only"], names = ["--check-configs-only"],
paramLabel = "<BOOLEAN>", paramLabel = "<BOOLEAN>",
description = ["Validates configuration files only, without starting the application."], description = ["Validates configuration files only, without starting the application."],
arity = "0..1" arity = "0..1",
) )
private var checkConfigsOnly: Boolean = false private var checkConfigsOnly: Boolean = false
override fun call(): Int { override fun call(): Int {
@@ -97,7 +94,7 @@ internal constructor(private val errorWriter: PrintWriter, private val startActi
tracesLimitsFileV2 = tracesLimitsV2File.toPath(), tracesLimitsFileV2 = tracesLimitsV2File.toPath(),
smartContractErrorsFile = smartContractErrorsFile.toPath(), smartContractErrorsFile = smartContractErrorsFile.toPath(),
gasPriceCapTimeOfDayMultipliersFile = gasPriceCapTimeOfDayMultipliersFile.toPath(), gasPriceCapTimeOfDayMultipliersFile = gasPriceCapTimeOfDayMultipliersFile.toPath(),
logger = logger logger = logger,
) )
if (checkConfigsOnly) { if (checkConfigsOnly) {

View File

@@ -39,7 +39,7 @@ class CoordinatorAppMain {
// Messages in App.stop won't appear in the logs // Messages in App.stop won't appear in the logs
Configurator.shutdown(LogManager.getContext() as LoggerContext) Configurator.shutdown(LogManager.getContext() as LoggerContext)
} }
} },
) )
app.start() app.start()
} }

View File

@@ -116,7 +116,7 @@ class L1DependentApp(
private val aggregationsRepository: AggregationsRepository, private val aggregationsRepository: AggregationsRepository,
l1FeeHistoriesRepository: FeeHistoriesRepositoryWithCache, l1FeeHistoriesRepository: FeeHistoriesRepositoryWithCache,
private val smartContractErrors: SmartContractErrors, private val smartContractErrors: SmartContractErrors,
private val metricsFacade: MetricsFacade private val metricsFacade: MetricsFacade,
) : LongRunningService { ) : LongRunningService {
private val log = LogManager.getLogger(this::class.java) private val log = LogManager.getLogger(this::class.java)
@@ -132,13 +132,13 @@ class L1DependentApp(
private val l2TransactionManager = createTransactionManager( private val l2TransactionManager = createTransactionManager(
vertx, vertx,
configs.l2Signer, configs.l2Signer,
l2Web3jClient l2Web3jClient,
) )
private val l1Web3jClient = createWeb3jHttpClient( private val l1Web3jClient = createWeb3jHttpClient(
rpcUrl = configs.l1.rpcEndpoint.toString(), rpcUrl = configs.l1.rpcEndpoint.toString(),
log = LogManager.getLogger("clients.l1.eth-api"), log = LogManager.getLogger("clients.l1.eth-api"),
pollingInterval = 1.seconds pollingInterval = 1.seconds,
) )
private val l1Web3jService = Web3jBlobExtended(HttpService(configs.l1.ethFeeHistoryEndpoint.toString())) private val l1Web3jService = Web3jBlobExtended(HttpService(configs.l1.ethFeeHistoryEndpoint.toString()))
@@ -147,7 +147,7 @@ class L1DependentApp(
private val proverClientFactory = ProverClientFactory( private val proverClientFactory = ProverClientFactory(
vertx = vertx, vertx = vertx,
config = configs.proversConfig, config = configs.proversConfig,
metricsFacade = metricsFacade metricsFacade = metricsFacade,
) )
private val l2ExtendedWeb3j = ExtendedWeb3JImpl(l2Web3jClient) private val l2ExtendedWeb3j = ExtendedWeb3JImpl(l2Web3jClient)
@@ -155,32 +155,32 @@ class L1DependentApp(
private val finalizationTransactionManager = createTransactionManager( private val finalizationTransactionManager = createTransactionManager(
vertx, vertx,
configs.finalizationSigner, configs.finalizationSigner,
l1Web3jClient l1Web3jClient,
) )
private val l1MinPriorityFeeCalculator: FeesCalculator = WMAFeesCalculator( private val l1MinPriorityFeeCalculator: FeesCalculator = WMAFeesCalculator(
WMAFeesCalculator.Config( WMAFeesCalculator.Config(
baseFeeCoefficient = 0.0, baseFeeCoefficient = 0.0,
priorityFeeWmaCoefficient = 1.0 priorityFeeWmaCoefficient = 1.0,
) ),
) )
private val l1DataSubmissionPriorityFeeCalculator: FeesCalculator = BoundableFeeCalculator( private val l1DataSubmissionPriorityFeeCalculator: FeesCalculator = BoundableFeeCalculator(
BoundableFeeCalculator.Config( BoundableFeeCalculator.Config(
feeUpperBound = configs.blobSubmission.priorityFeePerGasUpperBound.toDouble(), feeUpperBound = configs.blobSubmission.priorityFeePerGasUpperBound.toDouble(),
feeLowerBound = configs.blobSubmission.priorityFeePerGasLowerBound.toDouble(), feeLowerBound = configs.blobSubmission.priorityFeePerGasLowerBound.toDouble(),
feeMargin = 0.0 feeMargin = 0.0,
), ),
l1MinPriorityFeeCalculator l1MinPriorityFeeCalculator,
) )
private val l1FinalizationPriorityFeeCalculator: FeesCalculator = BoundableFeeCalculator( private val l1FinalizationPriorityFeeCalculator: FeesCalculator = BoundableFeeCalculator(
BoundableFeeCalculator.Config( BoundableFeeCalculator.Config(
feeUpperBound = configs.l1.maxPriorityFeePerGasCap.toDouble() * configs.l1.gasPriceCapMultiplierForFinalization, feeUpperBound = configs.l1.maxPriorityFeePerGasCap.toDouble() * configs.l1.gasPriceCapMultiplierForFinalization,
feeLowerBound = 0.0, feeLowerBound = 0.0,
feeMargin = 0.0 feeMargin = 0.0,
), ),
l1MinPriorityFeeCalculator l1MinPriorityFeeCalculator,
) )
private val feesFetcher: FeesFetcher = FeeHistoryFetcherImpl( private val feesFetcher: FeesFetcher = FeeHistoryFetcherImpl(
@@ -188,13 +188,13 @@ class L1DependentApp(
l1Web3jService, l1Web3jService,
FeeHistoryFetcherImpl.Config( FeeHistoryFetcherImpl.Config(
configs.l1.feeHistoryBlockCount.toUInt(), configs.l1.feeHistoryBlockCount.toUInt(),
configs.l1.feeHistoryRewardPercentile configs.l1.feeHistoryRewardPercentile,
) ),
) )
private val lineaRollupClient: LineaRollupSmartContractClientReadOnly = Web3JLineaRollupSmartContractClientReadOnly( private val lineaRollupClient: LineaRollupSmartContractClientReadOnly = Web3JLineaRollupSmartContractClientReadOnly(
contractAddress = configs.l1.zkEvmContractAddress, contractAddress = configs.l1.zkEvmContractAddress,
web3j = l1Web3jClient web3j = l1Web3jClient,
) )
private val l1FinalizationMonitor = run { private val l1FinalizationMonitor = run {
@@ -202,11 +202,11 @@ class L1DependentApp(
config = config =
FinalizationMonitorImpl.Config( FinalizationMonitorImpl.Config(
pollingInterval = configs.l1.finalizationPollingInterval.toKotlinDuration(), pollingInterval = configs.l1.finalizationPollingInterval.toKotlinDuration(),
l1QueryBlockTag = configs.l1.l1QueryBlockTag l1QueryBlockTag = configs.l1.l1QueryBlockTag,
), ),
contract = lineaRollupClient, contract = lineaRollupClient,
l2Client = l2Web3jClient, l2Client = l2Web3jClient,
vertx = vertx vertx = vertx,
) )
} }
@@ -215,7 +215,7 @@ class L1DependentApp(
httpJsonRpcClientFactory = httpJsonRpcClientFactory, httpJsonRpcClientFactory = httpJsonRpcClientFactory,
lineaRollupClient = lineaRollupClient, lineaRollupClient = lineaRollupClient,
l2Web3jClient = l2Web3jClient, l2Web3jClient = l2Web3jClient,
vertx = vertx vertx = vertx,
) )
private val gasPriceCapProvider = private val gasPriceCapProvider =
@@ -246,11 +246,11 @@ class L1DependentApp(
finalizationTargetMaxDelay = finalizationTargetMaxDelay =
configs.l1DynamicGasPriceCapService.gasPriceCapCalculation.finalizationTargetMaxDelay.toKotlinDuration(), configs.l1DynamicGasPriceCapService.gasPriceCapCalculation.finalizationTargetMaxDelay.toKotlinDuration(),
gasPriceCapsCoefficient = gasPriceCapsCoefficient =
configs.l1DynamicGasPriceCapService.gasPriceCapCalculation.gasPriceCapsCheckCoefficient configs.l1DynamicGasPriceCapService.gasPriceCapCalculation.gasPriceCapsCheckCoefficient,
), ),
l2ExtendedWeb3JClient = l2ExtendedWeb3j, l2ExtendedWeb3JClient = l2ExtendedWeb3j,
feeHistoriesRepository = l1FeeHistoriesRepository, feeHistoriesRepository = l1FeeHistoriesRepository,
gasPriceCapCalculator = l1GasPriceCapCalculator gasPriceCapCalculator = l1GasPriceCapCalculator,
) )
} else { } else {
null null
@@ -261,10 +261,10 @@ class L1DependentApp(
config = GasPriceCapProviderForDataSubmission.Config( config = GasPriceCapProviderForDataSubmission.Config(
maxPriorityFeePerGasCap = configs.l1.maxPriorityFeePerGasCap, maxPriorityFeePerGasCap = configs.l1.maxPriorityFeePerGasCap,
maxFeePerGasCap = configs.l1.maxFeePerGasCap, maxFeePerGasCap = configs.l1.maxFeePerGasCap,
maxFeePerBlobGasCap = configs.l1.maxFeePerBlobGasCap maxFeePerBlobGasCap = configs.l1.maxFeePerBlobGasCap,
), ),
gasPriceCapProvider = gasPriceCapProvider!!, gasPriceCapProvider = gasPriceCapProvider!!,
metricsFacade = metricsFacade metricsFacade = metricsFacade,
) )
} else { } else {
null null
@@ -275,10 +275,10 @@ class L1DependentApp(
config = GasPriceCapProviderForFinalization.Config( config = GasPriceCapProviderForFinalization.Config(
maxPriorityFeePerGasCap = configs.l1.maxPriorityFeePerGasCap, maxPriorityFeePerGasCap = configs.l1.maxPriorityFeePerGasCap,
maxFeePerGasCap = configs.l1.maxFeePerGasCap, maxFeePerGasCap = configs.l1.maxFeePerGasCap,
gasPriceCapMultiplier = configs.l1.gasPriceCapMultiplierForFinalization gasPriceCapMultiplier = configs.l1.gasPriceCapMultiplierForFinalization,
), ),
gasPriceCapProvider = gasPriceCapProvider!!, gasPriceCapProvider = gasPriceCapProvider!!,
metricsFacade = metricsFacade metricsFacade = metricsFacade,
) )
} else { } else {
null null
@@ -287,11 +287,11 @@ class L1DependentApp(
private val lastFinalizedBlock = lastFinalizedBlock().get() private val lastFinalizedBlock = lastFinalizedBlock().get()
private val lastProcessedBlockNumber = resumeConflationFrom( private val lastProcessedBlockNumber = resumeConflationFrom(
aggregationsRepository, aggregationsRepository,
lastFinalizedBlock lastFinalizedBlock,
).get() ).get()
private val lastConsecutiveAggregatedBlockNumber = resumeAggregationFrom( private val lastConsecutiveAggregatedBlockNumber = resumeAggregationFrom(
aggregationsRepository, aggregationsRepository,
lastFinalizedBlock lastFinalizedBlock,
).get() ).get()
private fun createDeadlineConflationCalculatorRunner(): DeadlineConflationCalculatorRunner { private fun createDeadlineConflationCalculatorRunner(): DeadlineConflationCalculatorRunner {
@@ -301,15 +301,15 @@ class L1DependentApp(
config = ConflationCalculatorByTimeDeadline.Config( config = ConflationCalculatorByTimeDeadline.Config(
conflationDeadline = configs.conflation.conflationDeadline.toKotlinDuration(), conflationDeadline = configs.conflation.conflationDeadline.toKotlinDuration(),
conflationDeadlineLastBlockConfirmationDelay = conflationDeadlineLastBlockConfirmationDelay =
configs.conflation.conflationDeadlineLastBlockConfirmationDelay.toKotlinDuration() configs.conflation.conflationDeadlineLastBlockConfirmationDelay.toKotlinDuration(),
), ),
lastBlockNumber = lastProcessedBlockNumber, lastBlockNumber = lastProcessedBlockNumber,
clock = Clock.System, clock = Clock.System,
latestBlockProvider = GethCliqueSafeBlockProvider( latestBlockProvider = GethCliqueSafeBlockProvider(
l2ExtendedWeb3j.web3jClient, l2ExtendedWeb3j.web3jClient,
GethCliqueSafeBlockProvider.Config(configs.l2.blocksToFinalization.toLong()) GethCliqueSafeBlockProvider.Config(configs.l2.blocksToFinalization.toLong()),
) ),
) ),
) )
} }
@@ -320,8 +320,8 @@ class L1DependentApp(
if (configs.conflation.blocksLimit != null) { if (configs.conflation.blocksLimit != null) {
calculators.add( calculators.add(
ConflationCalculatorByBlockLimit( ConflationCalculatorByBlockLimit(
blockLimit = configs.conflation.blocksLimit.toUInt() blockLimit = configs.conflation.blocksLimit.toUInt(),
) ),
) )
} }
} }
@@ -330,15 +330,15 @@ class L1DependentApp(
if (configs.conflation.conflationTargetEndBlockNumbers.isNotEmpty()) { if (configs.conflation.conflationTargetEndBlockNumbers.isNotEmpty()) {
calculators.add( calculators.add(
ConflationCalculatorByTargetBlockNumbers( ConflationCalculatorByTargetBlockNumbers(
targetEndBlockNumbers = configs.conflation.conflationTargetEndBlockNumbers targetEndBlockNumbers = configs.conflation.conflationTargetEndBlockNumbers,
) ),
) )
} }
} }
private fun createCalculatorsForBlobsAndConflation( private fun createCalculatorsForBlobsAndConflation(
logger: Logger, logger: Logger,
compressedBlobCalculator: ConflationCalculatorByDataCompressed compressedBlobCalculator: ConflationCalculatorByDataCompressed,
): List<ConflationCalculator> { ): List<ConflationCalculator> {
val calculators: MutableList<ConflationCalculator> = val calculators: MutableList<ConflationCalculator> =
mutableListOf( mutableListOf(
@@ -346,9 +346,9 @@ class L1DependentApp(
tracesCountersLimit = configs.conflation.tracesLimitsV2, tracesCountersLimit = configs.conflation.tracesLimitsV2,
emptyTracesCounters = TracesCountersV2.EMPTY_TRACES_COUNT, emptyTracesCounters = TracesCountersV2.EMPTY_TRACES_COUNT,
metricsFacade = metricsFacade, metricsFacade = metricsFacade,
log = logger log = logger,
), ),
compressedBlobCalculator compressedBlobCalculator,
) )
addBlocksLimitCalculatorIfDefined(calculators) addBlocksLimitCalculatorIfDefined(calculators)
addTargetEndBlockConflationCalculatorIfDefined(calculators) addTargetEndBlockConflationCalculatorIfDefined(calculators)
@@ -363,18 +363,18 @@ class L1DependentApp(
val blobCompressor = GoBackedBlobCompressor.getInstance( val blobCompressor = GoBackedBlobCompressor.getInstance(
compressorVersion = compressorVersion, compressorVersion = compressorVersion,
dataLimit = configs.blobCompression.blobSizeLimit.toUInt(), dataLimit = configs.blobCompression.blobSizeLimit.toUInt(),
metricsFacade = metricsFacade metricsFacade = metricsFacade,
) )
val compressedBlobCalculator = ConflationCalculatorByDataCompressed( val compressedBlobCalculator = ConflationCalculatorByDataCompressed(
blobCompressor = blobCompressor blobCompressor = blobCompressor,
) )
val globalCalculator = GlobalBlockConflationCalculator( val globalCalculator = GlobalBlockConflationCalculator(
lastBlockNumber = lastProcessedBlockNumber, lastBlockNumber = lastProcessedBlockNumber,
syncCalculators = createCalculatorsForBlobsAndConflation(logger, compressedBlobCalculator), syncCalculators = createCalculatorsForBlobsAndConflation(logger, compressedBlobCalculator),
deferredTriggerConflationCalculators = listOf(deadlineConflationCalculatorRunnerNew), deferredTriggerConflationCalculators = listOf(deadlineConflationCalculatorRunnerNew),
emptyTracesCounters = TracesCountersV2.EMPTY_TRACES_COUNT, emptyTracesCounters = TracesCountersV2.EMPTY_TRACES_COUNT,
log = logger log = logger,
) )
val batchesLimit = val batchesLimit =
@@ -384,7 +384,7 @@ class L1DependentApp(
conflationCalculator = globalCalculator, conflationCalculator = globalCalculator,
blobCalculator = compressedBlobCalculator, blobCalculator = compressedBlobCalculator,
metricsFacade = metricsFacade, metricsFacade = metricsFacade,
batchesLimit = batchesLimit batchesLimit = batchesLimit,
) )
} }
private val conflationService: ConflationService = private val conflationService: ConflationService =
@@ -396,7 +396,7 @@ class L1DependentApp(
maxInflightRequestsPerClient = configs.stateManager.requestLimitPerEndpoint, maxInflightRequestsPerClient = configs.stateManager.requestLimitPerEndpoint,
requestRetry = configs.stateManager.requestRetryConfig, requestRetry = configs.stateManager.requestRetryConfig,
zkStateManagerVersion = configs.stateManager.version, zkStateManagerVersion = configs.stateManager.version,
logger = LogManager.getLogger("clients.StateManagerShomeiClient") logger = LogManager.getLogger("clients.StateManagerShomeiClient"),
) )
private val lineaSmartContractClientForDataSubmission: LineaRollupSmartContractClient = run { private val lineaSmartContractClientForDataSubmission: LineaRollupSmartContractClient = run {
@@ -411,26 +411,26 @@ class L1DependentApp(
gasLimit = configs.l1.gasLimit, gasLimit = configs.l1.gasLimit,
maxFeePerGasCap = configs.l1.maxFeePerGasCap, maxFeePerGasCap = configs.l1.maxFeePerGasCap,
maxPriorityFeePerGasCap = configs.l1.maxPriorityFeePerGasCap, maxPriorityFeePerGasCap = configs.l1.maxPriorityFeePerGasCap,
maxFeePerBlobGasCap = configs.l1.maxFeePerBlobGasCap maxFeePerBlobGasCap = configs.l1.maxFeePerBlobGasCap,
) ),
) )
createLineaRollupContractClient( createLineaRollupContractClient(
l1Config = configs.l1, l1Config = configs.l1,
transactionManager = createTransactionManager( transactionManager = createTransactionManager(
vertx, vertx,
configs.dataSubmissionSigner, configs.dataSubmissionSigner,
l1Web3jClient l1Web3jClient,
), ),
contractGasProvider = primaryOrFallbackGasProvider, contractGasProvider = primaryOrFallbackGasProvider,
web3jClient = l1Web3jClient, web3jClient = l1Web3jClient,
smartContractErrors = smartContractErrors, smartContractErrors = smartContractErrors,
useEthEstimateGas = configs.blobSubmission.useEthEstimateGas useEthEstimateGas = configs.blobSubmission.useEthEstimateGas,
) )
} }
private val genesisStateProvider = GenesisStateProvider( private val genesisStateProvider = GenesisStateProvider(
configs.l1.genesisStateRootHash, configs.l1.genesisStateRootHash,
configs.l1.genesisShnarfV6 configs.l1.genesisShnarfV6,
) )
private val blobCompressionProofCoordinator = run { private val blobCompressionProofCoordinator = run {
@@ -440,14 +440,14 @@ class L1DependentApp(
category = LineaMetricsCategory.BLOB, category = LineaMetricsCategory.BLOB,
name = "proven.highest.block.number", name = "proven.highest.block.number",
description = "Highest proven blob compression block number", description = "Highest proven blob compression block number",
measurementSupplier = highestProvenBlobTracker measurementSupplier = highestProvenBlobTracker,
) )
highestProvenBlobTracker highestProvenBlobTracker
} }
val blobCompressionProofHandler: (BlobCompressionProofUpdate) -> SafeFuture<*> = SimpleCompositeSafeFutureHandler( val blobCompressionProofHandler: (BlobCompressionProofUpdate) -> SafeFuture<*> = SimpleCompositeSafeFutureHandler(
listOf( listOf(
maxProvenBlobCache maxProvenBlobCache,
) ),
) )
val blobCompressionProofCoordinator = BlobCompressionProofCoordinator( val blobCompressionProofCoordinator = BlobCompressionProofCoordinator(
@@ -457,33 +457,33 @@ class L1DependentApp(
rollingBlobShnarfCalculator = RollingBlobShnarfCalculator( rollingBlobShnarfCalculator = RollingBlobShnarfCalculator(
blobShnarfCalculator = GoBackedBlobShnarfCalculator( blobShnarfCalculator = GoBackedBlobShnarfCalculator(
version = ShnarfCalculatorVersion.V1_2, version = ShnarfCalculatorVersion.V1_2,
metricsFacade = metricsFacade metricsFacade = metricsFacade,
), ),
blobsRepository = blobsRepository, blobsRepository = blobsRepository,
genesisShnarf = genesisStateProvider.shnarf genesisShnarf = genesisStateProvider.shnarf,
), ),
blobZkStateProvider = BlobZkStateProviderImpl( blobZkStateProvider = BlobZkStateProviderImpl(
zkStateClient = zkStateClient zkStateClient = zkStateClient,
), ),
config = BlobCompressionProofCoordinator.Config( config = BlobCompressionProofCoordinator.Config(
pollingInterval = configs.blobCompression.handlerPollingInterval.toKotlinDuration() pollingInterval = configs.blobCompression.handlerPollingInterval.toKotlinDuration(),
), ),
blobCompressionProofHandler = blobCompressionProofHandler, blobCompressionProofHandler = blobCompressionProofHandler,
metricsFacade = metricsFacade metricsFacade = metricsFacade,
) )
val highestUnprovenBlobTracker = HighestUnprovenBlobTracker(lastProcessedBlockNumber) val highestUnprovenBlobTracker = HighestUnprovenBlobTracker(lastProcessedBlockNumber)
metricsFacade.createGauge( metricsFacade.createGauge(
category = LineaMetricsCategory.BLOB, category = LineaMetricsCategory.BLOB,
name = "unproven.highest.block.number", name = "unproven.highest.block.number",
description = "Block number of highest unproven blob produced", description = "Block number of highest unproven blob produced",
measurementSupplier = highestUnprovenBlobTracker measurementSupplier = highestUnprovenBlobTracker,
) )
val compositeSafeFutureHandler = SimpleCompositeSafeFutureHandler( val compositeSafeFutureHandler = SimpleCompositeSafeFutureHandler(
listOf( listOf(
blobCompressionProofCoordinator::handleBlob, blobCompressionProofCoordinator::handleBlob,
highestUnprovenBlobTracker highestUnprovenBlobTracker,
) ),
) )
conflationCalculator.onBlobCreation(compositeSafeFutureHandler) conflationCalculator.onBlobCreation(compositeSafeFutureHandler)
blobCompressionProofCoordinator blobCompressionProofCoordinator
@@ -494,14 +494,14 @@ class L1DependentApp(
category = LineaMetricsCategory.BLOB, category = LineaMetricsCategory.BLOB,
name = "highest.accepted.block.number", name = "highest.accepted.block.number",
description = "Highest accepted blob end block number", description = "Highest accepted blob end block number",
measurementSupplier = it measurementSupplier = it,
) )
} }
private val alreadySubmittedBlobsFilter = private val alreadySubmittedBlobsFilter =
L1ShnarfBasedAlreadySubmittedBlobsFilter( L1ShnarfBasedAlreadySubmittedBlobsFilter(
lineaRollup = lineaSmartContractClientForDataSubmission, lineaRollup = lineaSmartContractClientForDataSubmission,
acceptedBlobEndBlockNumberConsumer = { highestAcceptedBlobTracker(it) } acceptedBlobEndBlockNumberConsumer = { highestAcceptedBlobTracker(it) },
) )
private val latestBlobSubmittedBlockNumberTracker = LatestBlobSubmittedBlockNumberTracker(0UL) private val latestBlobSubmittedBlockNumberTracker = LatestBlobSubmittedBlockNumberTracker(0UL)
@@ -513,14 +513,14 @@ class L1DependentApp(
category = LineaMetricsCategory.BLOB, category = LineaMetricsCategory.BLOB,
name = "highest.submitted.on.l1", name = "highest.submitted.on.l1",
description = "Highest submitted blob end block number on l1", description = "Highest submitted blob end block number on l1",
measurementSupplier = { latestBlobSubmittedBlockNumberTracker.get() } measurementSupplier = { latestBlobSubmittedBlockNumberTracker.get() },
) )
val blobSubmissionDelayHistogram = metricsFacade.createHistogram( val blobSubmissionDelayHistogram = metricsFacade.createHistogram(
category = LineaMetricsCategory.BLOB, category = LineaMetricsCategory.BLOB,
name = "submission.delay", name = "submission.delay",
description = "Delay between blob submission and end block timestamps", description = "Delay between blob submission and end block timestamps",
baseUnit = "seconds" baseUnit = "seconds",
) )
val blobSubmittedEventConsumers: Map<Consumer<BlobSubmittedEvent>, String> = mapOf( val blobSubmittedEventConsumers: Map<Consumer<BlobSubmittedEvent>, String> = mapOf(
@@ -529,7 +529,7 @@ class L1DependentApp(
} to "Submitted Blob Tracker Consumer", } to "Submitted Blob Tracker Consumer",
Consumer<BlobSubmittedEvent> { blobSubmission -> Consumer<BlobSubmittedEvent> { blobSubmission ->
blobSubmissionDelayHistogram.record(blobSubmission.getSubmissionDelay().toDouble()) blobSubmissionDelayHistogram.record(blobSubmission.getSubmissionDelay().toDouble())
} to "Blob Submission Delay Consumer" } to "Blob Submission Delay Consumer",
) )
BlobSubmissionCoordinator.create( BlobSubmissionCoordinator.create(
@@ -537,7 +537,7 @@ class L1DependentApp(
configs.blobSubmission.dbPollingInterval.toKotlinDuration(), configs.blobSubmission.dbPollingInterval.toKotlinDuration(),
configs.blobSubmission.proofSubmissionDelay.toKotlinDuration(), configs.blobSubmission.proofSubmissionDelay.toKotlinDuration(),
configs.blobSubmission.maxBlobsToSubmitPerTick.toUInt(), configs.blobSubmission.maxBlobsToSubmitPerTick.toUInt(),
configs.blobSubmission.targetBlobsToSendPerTransaction.toUInt() configs.blobSubmission.targetBlobsToSendPerTransaction.toUInt(),
), ),
blobsRepository = blobsRepository, blobsRepository = blobsRepository,
aggregationsRepository = aggregationsRepository, aggregationsRepository = aggregationsRepository,
@@ -546,7 +546,7 @@ class L1DependentApp(
alreadySubmittedBlobsFilter = alreadySubmittedBlobsFilter, alreadySubmittedBlobsFilter = alreadySubmittedBlobsFilter,
blobSubmittedEventDispatcher = EventDispatcher(blobSubmittedEventConsumers), blobSubmittedEventDispatcher = EventDispatcher(blobSubmittedEventConsumers),
vertx = vertx, vertx = vertx,
clock = Clock.System clock = Clock.System,
) )
} }
} }
@@ -554,14 +554,14 @@ class L1DependentApp(
private val proofAggregationCoordinatorService: LongRunningService = run { private val proofAggregationCoordinatorService: LongRunningService = run {
val maxBlobEndBlockNumberTracker = ConsecutiveProvenBlobsProviderWithLastEndBlockNumberTracker( val maxBlobEndBlockNumberTracker = ConsecutiveProvenBlobsProviderWithLastEndBlockNumberTracker(
aggregationsRepository, aggregationsRepository,
lastProcessedBlockNumber lastProcessedBlockNumber,
) )
metricsFacade.createGauge( metricsFacade.createGauge(
category = LineaMetricsCategory.BLOB, category = LineaMetricsCategory.BLOB,
name = "proven.highest.consecutive.block.number", name = "proven.highest.consecutive.block.number",
description = "Highest consecutive proven blob compression block number", description = "Highest consecutive proven blob compression block number",
measurementSupplier = maxBlobEndBlockNumberTracker measurementSupplier = maxBlobEndBlockNumberTracker,
) )
val highestAggregationTracker = HighestULongTracker(lastProcessedBlockNumber) val highestAggregationTracker = HighestULongTracker(lastProcessedBlockNumber)
@@ -569,7 +569,7 @@ class L1DependentApp(
category = LineaMetricsCategory.AGGREGATION, category = LineaMetricsCategory.AGGREGATION,
name = "proven.highest.block.number", name = "proven.highest.block.number",
description = "Highest proven aggregation block number", description = "Highest proven aggregation block number",
measurementSupplier = highestAggregationTracker measurementSupplier = highestAggregationTracker,
) )
ProofAggregationCoordinatorService ProofAggregationCoordinatorService
@@ -581,7 +581,7 @@ class L1DependentApp(
aggregationDeadline = configs.proofAggregation.aggregationDeadline.toKotlinDuration(), aggregationDeadline = configs.proofAggregation.aggregationDeadline.toKotlinDuration(),
latestBlockProvider = GethCliqueSafeBlockProvider( latestBlockProvider = GethCliqueSafeBlockProvider(
l2ExtendedWeb3j.web3jClient, l2ExtendedWeb3j.web3jClient,
GethCliqueSafeBlockProvider.Config(configs.l2.blocksToFinalization.toLong()) GethCliqueSafeBlockProvider.Config(configs.l2.blocksToFinalization.toLong()),
), ),
maxProofsPerAggregation = configs.proofAggregation.aggregationProofsLimit.toUInt(), maxProofsPerAggregation = configs.proofAggregation.aggregationProofsLimit.toUInt(),
startBlockNumberInclusive = lastConsecutiveAggregatedBlockNumber + 1u, startBlockNumberInclusive = lastConsecutiveAggregatedBlockNumber + 1u,
@@ -592,9 +592,9 @@ class L1DependentApp(
l2Web3jClient, l2Web3jClient,
requestRetryConfig = linea.domain.RetryConfig( requestRetryConfig = linea.domain.RetryConfig(
backoffDelay = 1.seconds, backoffDelay = 1.seconds,
failuresWarningThreshold = 3u failuresWarningThreshold = 3u,
), ),
vertx = vertx vertx = vertx,
), ),
l2MessageService = Web3JL2MessageServiceSmartContractClient.create( l2MessageService = Web3JL2MessageServiceSmartContractClient.create(
web3jClient = l2Web3jClient, web3jClient = l2Web3jClient,
@@ -605,13 +605,13 @@ class L1DependentApp(
feeHistoryRewardPercentile = configs.l2.feeHistoryRewardPercentile, feeHistoryRewardPercentile = configs.l2.feeHistoryRewardPercentile,
transactionManager = l2TransactionManager, transactionManager = l2TransactionManager,
smartContractErrors = smartContractErrors, smartContractErrors = smartContractErrors,
smartContractDeploymentBlockNumber = configs.l2.messageServiceDeploymentBlockNumber smartContractDeploymentBlockNumber = configs.l2.messageServiceDeploymentBlockNumber,
), ),
aggregationDeadlineDelay = configs.conflation.conflationDeadlineLastBlockConfirmationDelay.toKotlinDuration(), aggregationDeadlineDelay = configs.conflation.conflationDeadlineLastBlockConfirmationDelay.toKotlinDuration(),
targetEndBlockNumbers = configs.proofAggregation.targetEndBlocks, targetEndBlockNumbers = configs.proofAggregation.targetEndBlocks,
metricsFacade = metricsFacade, metricsFacade = metricsFacade,
provenAggregationEndBlockNumberConsumer = { highestAggregationTracker(it) }, provenAggregationEndBlockNumberConsumer = { highestAggregationTracker(it) },
aggregationSizeMultipleOf = configs.proofAggregation.aggregationSizeMultipleOf.toUInt() aggregationSizeMultipleOf = configs.proofAggregation.aggregationSizeMultipleOf.toUInt(),
) )
} }
@@ -636,8 +636,8 @@ class L1DependentApp(
configs.l1.maxPriorityFeePerGasCap.toDouble() * configs.l1.maxPriorityFeePerGasCap.toDouble() *
configs.l1.gasPriceCapMultiplierForFinalization configs.l1.gasPriceCapMultiplierForFinalization
).toULong(), ).toULong(),
maxFeePerBlobGasCap = configs.l1.maxFeePerBlobGasCap maxFeePerBlobGasCap = configs.l1.maxFeePerBlobGasCap,
) ),
) )
val lineaSmartContractClientForFinalization: LineaRollupSmartContractClient = createLineaRollupContractClient( val lineaSmartContractClientForFinalization: LineaRollupSmartContractClient = createLineaRollupContractClient(
l1Config = configs.l1, l1Config = configs.l1,
@@ -645,7 +645,7 @@ class L1DependentApp(
contractGasProvider = primaryOrFallbackGasProvider, contractGasProvider = primaryOrFallbackGasProvider,
web3jClient = l1Web3jClient, web3jClient = l1Web3jClient,
smartContractErrors = smartContractErrors, smartContractErrors = smartContractErrors,
useEthEstimateGas = configs.aggregationFinalization.useEthEstimateGas useEthEstimateGas = configs.aggregationFinalization.useEthEstimateGas,
) )
val latestFinalizationSubmittedBlockNumberTracker = LatestFinalizationSubmittedBlockNumberTracker(0UL) val latestFinalizationSubmittedBlockNumberTracker = LatestFinalizationSubmittedBlockNumberTracker(0UL)
@@ -653,14 +653,14 @@ class L1DependentApp(
category = LineaMetricsCategory.AGGREGATION, category = LineaMetricsCategory.AGGREGATION,
name = "highest.submitted.on.l1", name = "highest.submitted.on.l1",
description = "Highest submitted finalization end block number on l1", description = "Highest submitted finalization end block number on l1",
measurementSupplier = { latestFinalizationSubmittedBlockNumberTracker.get() } measurementSupplier = { latestFinalizationSubmittedBlockNumberTracker.get() },
) )
val finalizationSubmissionDelayHistogram = metricsFacade.createHistogram( val finalizationSubmissionDelayHistogram = metricsFacade.createHistogram(
category = LineaMetricsCategory.AGGREGATION, category = LineaMetricsCategory.AGGREGATION,
name = "submission.delay", name = "submission.delay",
description = "Delay between finalization submission and end block timestamps", description = "Delay between finalization submission and end block timestamps",
baseUnit = "seconds" baseUnit = "seconds",
) )
val submittedFinalizationConsumers: Map<Consumer<FinalizationSubmittedEvent>, String> = mapOf( val submittedFinalizationConsumers: Map<Consumer<FinalizationSubmittedEvent>, String> = mapOf(
@@ -669,13 +669,13 @@ class L1DependentApp(
} to "Finalization Submission Consumer", } to "Finalization Submission Consumer",
Consumer<FinalizationSubmittedEvent> { finalizationSubmission -> Consumer<FinalizationSubmittedEvent> { finalizationSubmission ->
finalizationSubmissionDelayHistogram.record(finalizationSubmission.getSubmissionDelay().toDouble()) finalizationSubmissionDelayHistogram.record(finalizationSubmission.getSubmissionDelay().toDouble())
} to "Finalization Submission Delay Consumer" } to "Finalization Submission Delay Consumer",
) )
AggregationFinalizationCoordinator.create( AggregationFinalizationCoordinator.create(
config = AggregationFinalizationCoordinator.Config( config = AggregationFinalizationCoordinator.Config(
configs.aggregationFinalization.dbPollingInterval.toKotlinDuration(), configs.aggregationFinalization.dbPollingInterval.toKotlinDuration(),
configs.aggregationFinalization.proofSubmissionDelay.toKotlinDuration() configs.aggregationFinalization.proofSubmissionDelay.toKotlinDuration(),
), ),
aggregationsRepository = aggregationsRepository, aggregationsRepository = aggregationsRepository,
blobsRepository = blobsRepository, blobsRepository = blobsRepository,
@@ -684,10 +684,10 @@ class L1DependentApp(
aggregationSubmitter = AggregationSubmitterImpl( aggregationSubmitter = AggregationSubmitterImpl(
lineaRollup = lineaSmartContractClientForFinalization, lineaRollup = lineaSmartContractClientForFinalization,
gasPriceCapProvider = gasPriceCapProviderForFinalization, gasPriceCapProvider = gasPriceCapProviderForFinalization,
aggregationSubmittedEventConsumer = EventDispatcher(submittedFinalizationConsumers) aggregationSubmittedEventConsumer = EventDispatcher(submittedFinalizationConsumers),
), ),
vertx = vertx, vertx = vertx,
clock = Clock.System clock = Clock.System,
) )
} }
} }
@@ -702,13 +702,13 @@ class L1DependentApp(
rpcClient = httpJsonRpcClientFactory.createWithLoadBalancing( rpcClient = httpJsonRpcClientFactory.createWithLoadBalancing(
endpoints = tracesCounterV2Config.endpoints.toSet(), endpoints = tracesCounterV2Config.endpoints.toSet(),
maxInflightRequestsPerClient = tracesCounterV2Config.requestLimitPerEndpoint, maxInflightRequestsPerClient = tracesCounterV2Config.requestLimitPerEndpoint,
log = tracesCountersLog log = tracesCountersLog,
), ),
config = TracesGeneratorJsonRpcClientV2.Config( config = TracesGeneratorJsonRpcClientV2.Config(
expectedTracesApiVersion = expectedTracesApiVersionV2 expectedTracesApiVersion = expectedTracesApiVersionV2,
), ),
retryConfig = tracesCounterV2Config.requestRetryConfig, retryConfig = tracesCounterV2Config.requestRetryConfig,
log = tracesCountersLog log = tracesCountersLog,
) )
} }
@@ -721,13 +721,13 @@ class L1DependentApp(
rpcClient = httpJsonRpcClientFactory.createWithLoadBalancing( rpcClient = httpJsonRpcClientFactory.createWithLoadBalancing(
endpoints = tracesConflationConfigV2.endpoints.toSet(), endpoints = tracesConflationConfigV2.endpoints.toSet(),
maxInflightRequestsPerClient = tracesConflationConfigV2.requestLimitPerEndpoint, maxInflightRequestsPerClient = tracesConflationConfigV2.requestLimitPerEndpoint,
log = tracesConflationLog log = tracesConflationLog,
), ),
config = TracesGeneratorJsonRpcClientV2.Config( config = TracesGeneratorJsonRpcClientV2.Config(
expectedTracesApiVersion = expectedTracesApiVersionV2 expectedTracesApiVersion = expectedTracesApiVersionV2,
), ),
retryConfig = tracesConflationConfigV2.requestRetryConfig, retryConfig = tracesConflationConfigV2.requestRetryConfig,
log = tracesConflationLog log = tracesConflationLog,
) )
} }
@@ -738,7 +738,7 @@ class L1DependentApp(
category = LineaMetricsCategory.BATCH, category = LineaMetricsCategory.BATCH,
name = "proven.highest.block.number", name = "proven.highest.block.number",
description = "Highest proven batch execution block number", description = "Highest proven batch execution block number",
measurementSupplier = highestProvenBatchTracker measurementSupplier = highestProvenBatchTracker,
) )
highestProvenBatchTracker highestProvenBatchTracker
} }
@@ -746,12 +746,12 @@ class L1DependentApp(
val batchProofHandler = SimpleCompositeSafeFutureHandler( val batchProofHandler = SimpleCompositeSafeFutureHandler(
listOf( listOf(
maxProvenBatchCache, maxProvenBatchCache,
BatchProofHandlerImpl(batchesRepository)::acceptNewBatch BatchProofHandlerImpl(batchesRepository)::acceptNewBatch,
) ),
) )
val executionProverClient: ExecutionProverClientV2 = proverClientFactory.executionProverClient( val executionProverClient: ExecutionProverClientV2 = proverClientFactory.executionProverClient(
tracesVersion = configs.traces.rawExecutionTracesVersion, tracesVersion = configs.traces.rawExecutionTracesVersion,
stateManagerVersion = configs.stateManager.version stateManagerVersion = configs.stateManager.version,
) )
val proofGeneratingConflationHandlerImpl = ProofGeneratingConflationHandlerImpl( val proofGeneratingConflationHandlerImpl = ProofGeneratingConflationHandlerImpl(
@@ -762,15 +762,15 @@ class L1DependentApp(
web3jClient = l2Web3jClient, web3jClient = l2Web3jClient,
requestRetryConfig = linea.domain.RetryConfig( requestRetryConfig = linea.domain.RetryConfig(
backoffDelay = 1.seconds, backoffDelay = 1.seconds,
failuresWarningThreshold = 3u failuresWarningThreshold = 3u,
), ),
vertx = vertx vertx = vertx,
), ),
messageServiceAddress = configs.l2.messageServiceAddress messageServiceAddress = configs.l2.messageServiceAddress,
), ),
batchProofHandler = batchProofHandler, batchProofHandler = batchProofHandler,
vertx = vertx, vertx = vertx,
config = ProofGeneratingConflationHandlerImpl.Config(5.seconds) config = ProofGeneratingConflationHandlerImpl.Config(5.seconds),
) )
val highestConflationTracker = HighestConflationTracker(lastProcessedBlockNumber) val highestConflationTracker = HighestConflationTracker(lastProcessedBlockNumber)
@@ -778,12 +778,12 @@ class L1DependentApp(
category = LineaMetricsCategory.CONFLATION, category = LineaMetricsCategory.CONFLATION,
name = "last.block.number", name = "last.block.number",
description = "Last conflated block number", description = "Last conflated block number",
measurementSupplier = highestConflationTracker measurementSupplier = highestConflationTracker,
) )
val conflationsCounter = metricsFacade.createCounter( val conflationsCounter = metricsFacade.createCounter(
category = LineaMetricsCategory.CONFLATION, category = LineaMetricsCategory.CONFLATION,
name = "counter", name = "counter",
description = "Counter of new conflations" description = "Counter of new conflations",
) )
SimpleCompositeSafeFutureHandler( SimpleCompositeSafeFutureHandler(
@@ -793,8 +793,8 @@ class L1DependentApp(
{ {
conflationsCounter.increment() conflationsCounter.increment()
SafeFuture.COMPLETE SafeFuture.COMPLETE
} },
) ),
) )
} }
@@ -804,20 +804,20 @@ class L1DependentApp(
conflationService = conflationService, conflationService = conflationService,
tracesCountersClient = tracesCountersClient, tracesCountersClient = tracesCountersClient,
vertx = vertx, vertx = vertx,
encoder = BlockRLPEncoder encoder = BlockRLPEncoder,
) )
} }
private val lastProvenBlockNumberProvider = run { private val lastProvenBlockNumberProvider = run {
val lastProvenConsecutiveBatchBlockNumberProvider = BatchesRepoBasedLastProvenBlockNumberProvider( val lastProvenConsecutiveBatchBlockNumberProvider = BatchesRepoBasedLastProvenBlockNumberProvider(
lastProcessedBlockNumber.toLong(), lastProcessedBlockNumber.toLong(),
batchesRepository batchesRepository,
) )
metricsFacade.createGauge( metricsFacade.createGauge(
category = LineaMetricsCategory.BATCH, category = LineaMetricsCategory.BATCH,
name = "proven.highest.consecutive.block.number", name = "proven.highest.consecutive.block.number",
description = "Highest proven consecutive execution batch block number", description = "Highest proven consecutive execution batch block number",
measurementSupplier = { lastProvenConsecutiveBatchBlockNumberProvider.getLastKnownProvenBlockNumber() } measurementSupplier = { lastProvenConsecutiveBatchBlockNumberProvider.getLastKnownProvenBlockNumber() },
) )
lastProvenConsecutiveBatchBlockNumberProvider lastProvenConsecutiveBatchBlockNumberProvider
} }
@@ -837,8 +837,8 @@ class L1DependentApp(
// We need to add 1 to l2InclusiveBlockNumberToStopAndFlushAggregation because conflation calculator requires // We need to add 1 to l2InclusiveBlockNumberToStopAndFlushAggregation because conflation calculator requires
// block_number = l2InclusiveBlockNumberToStopAndFlushAggregation + 1 to trigger conflation at // block_number = l2InclusiveBlockNumberToStopAndFlushAggregation + 1 to trigger conflation at
// l2InclusiveBlockNumberToStopAndFlushAggregation // l2InclusiveBlockNumberToStopAndFlushAggregation
lastL2BlockNumberToProcessInclusive = configs.l2InclusiveBlockNumberToStopAndFlushAggregation?.let { it + 1uL } lastL2BlockNumberToProcessInclusive = configs.l2InclusiveBlockNumberToStopAndFlushAggregation?.let { it + 1uL },
) ),
) )
blockCreationMonitor blockCreationMonitor
} }
@@ -847,7 +847,7 @@ class L1DependentApp(
val l1BasedLastFinalizedBlockProvider = L1BasedLastFinalizedBlockProvider( val l1BasedLastFinalizedBlockProvider = L1BasedLastFinalizedBlockProvider(
vertx, vertx,
lineaRollupClient, lineaRollupClient,
configs.conflation.consistentNumberOfBlocksOnL1ToWait.toUInt() configs.conflation.consistentNumberOfBlocksOnL1ToWait.toUInt(),
) )
return l1BasedLastFinalizedBlockProvider.getLastFinalizedBlock() return l1BasedLastFinalizedBlockProvider.getLastFinalizedBlock()
} }
@@ -867,12 +867,12 @@ class L1DependentApp(
l2HighestBlockTag = configs.messageAnchoring.l2HighestBlockTag, l2HighestBlockTag = configs.messageAnchoring.l2HighestBlockTag,
anchoringTickInterval = configs.messageAnchoring.anchoringTickInterval, anchoringTickInterval = configs.messageAnchoring.anchoringTickInterval,
messageQueueCapacity = configs.messageAnchoring.messageQueueCapacity, messageQueueCapacity = configs.messageAnchoring.messageQueueCapacity,
maxMessagesToAnchorPerL2Transaction = configs.messageAnchoring.maxMessagesToAnchorPerL2Transaction maxMessagesToAnchorPerL2Transaction = configs.messageAnchoring.maxMessagesToAnchorPerL2Transaction,
), ),
l1EthApiClient = createEthApiClient( l1EthApiClient = createEthApiClient(
web3jClient = l1Web3jClient, web3jClient = l1Web3jClient,
requestRetryConfig = null, requestRetryConfig = null,
vertx = vertx vertx = vertx,
), ),
l2MessageService = Web3JL2MessageServiceSmartContractClient.create( l2MessageService = Web3JL2MessageServiceSmartContractClient.create(
web3jClient = l2Web3jClient, web3jClient = l2Web3jClient,
@@ -883,8 +883,8 @@ class L1DependentApp(
feeHistoryRewardPercentile = configs.l2.feeHistoryRewardPercentile, feeHistoryRewardPercentile = configs.l2.feeHistoryRewardPercentile,
transactionManager = l2TransactionManager, transactionManager = l2TransactionManager,
smartContractErrors = smartContractErrors, smartContractErrors = smartContractErrors,
smartContractDeploymentBlockNumber = configs.l2.messageServiceDeploymentBlockNumber smartContractDeploymentBlockNumber = configs.l2.messageServiceDeploymentBlockNumber,
) ),
) )
} else { } else {
DisabledLongRunningService DisabledLongRunningService
@@ -897,7 +897,7 @@ class L1DependentApp(
httpJsonRpcClientFactory = httpJsonRpcClientFactory, httpJsonRpcClientFactory = httpJsonRpcClientFactory,
l1Web3jClient = l1Web3jClient, l1Web3jClient = l1Web3jClient,
l1Web3jService = l1Web3jService, l1Web3jService = l1Web3jService,
config = configs.l2NetworkGasPricingService config = configs.l2NetworkGasPricingService,
) )
} else { } else {
null null
@@ -916,16 +916,16 @@ class L1DependentApp(
val l1FeeHistoryWeb3jBlobExtClient = Web3jBlobExtended( val l1FeeHistoryWeb3jBlobExtClient = Web3jBlobExtended(
HttpService( HttpService(
configs.l1DynamicGasPriceCapService.feeHistoryFetcher.endpoint?.toString() configs.l1DynamicGasPriceCapService.feeHistoryFetcher.endpoint?.toString()
?: configs.l1.ethFeeHistoryEndpoint.toString() ?: configs.l1.ethFeeHistoryEndpoint.toString(),
) ),
) )
val l1FeeHistoryFetcher: GasPriceCapFeeHistoryFetcher = GasPriceCapFeeHistoryFetcherImpl( val l1FeeHistoryFetcher: GasPriceCapFeeHistoryFetcher = GasPriceCapFeeHistoryFetcherImpl(
web3jService = l1FeeHistoryWeb3jBlobExtClient, web3jService = l1FeeHistoryWeb3jBlobExtClient,
config = GasPriceCapFeeHistoryFetcherImpl.Config( config = GasPriceCapFeeHistoryFetcherImpl.Config(
maxBlockCount = configs.l1DynamicGasPriceCapService.feeHistoryFetcher.maxBlockCount, maxBlockCount = configs.l1DynamicGasPriceCapService.feeHistoryFetcher.maxBlockCount,
rewardPercentiles = configs.l1DynamicGasPriceCapService.feeHistoryFetcher.rewardPercentiles rewardPercentiles = configs.l1DynamicGasPriceCapService.feeHistoryFetcher.rewardPercentiles,
) ),
) )
FeeHistoryCachingService( FeeHistoryCachingService(
@@ -939,12 +939,12 @@ class L1DependentApp(
feeHistoryStoragePeriodInBlocks = feeHistoryStoragePeriodInBlocks, feeHistoryStoragePeriodInBlocks = feeHistoryStoragePeriodInBlocks,
feeHistoryWindowInBlocks = feeHistoryPercentileWindowInBlocks, feeHistoryWindowInBlocks = feeHistoryPercentileWindowInBlocks,
numOfBlocksBeforeLatest = numOfBlocksBeforeLatest =
configs.l1DynamicGasPriceCapService.feeHistoryFetcher.numOfBlocksBeforeLatest configs.l1DynamicGasPriceCapService.feeHistoryFetcher.numOfBlocksBeforeLatest,
), ),
vertx = vertx, vertx = vertx,
web3jClient = l1Web3jClient, web3jClient = l1Web3jClient,
feeHistoryFetcher = l1FeeHistoryFetcher, feeHistoryFetcher = l1FeeHistoryFetcher,
feeHistoriesRepository = l1FeeHistoriesRepository feeHistoriesRepository = l1FeeHistoriesRepository,
) )
} else { } else {
DisabledLongRunningService DisabledLongRunningService
@@ -955,7 +955,7 @@ class L1DependentApp(
category = LineaMetricsCategory.AGGREGATION, category = LineaMetricsCategory.AGGREGATION,
name = "highest.accepted.block.number", name = "highest.accepted.block.number",
description = "Highest finalized accepted end block number", description = "Highest finalized accepted end block number",
measurementSupplier = it measurementSupplier = it,
) )
} }
@@ -967,11 +967,11 @@ class L1DependentApp(
"finalized records cleanup" to RecordsCleanupFinalizationHandler( "finalized records cleanup" to RecordsCleanupFinalizationHandler(
batchesRepository = batchesRepository, batchesRepository = batchesRepository,
blobsRepository = blobsRepository, blobsRepository = blobsRepository,
aggregationsRepository = aggregationsRepository aggregationsRepository = aggregationsRepository,
), ),
"highest_accepted_finalization_on_l1" to FinalizationHandler { update: FinalizationMonitor.FinalizationUpdate -> "highest_accepted_finalization_on_l1" to FinalizationHandler { update: FinalizationMonitor.FinalizationUpdate ->
highestAcceptedFinalizationTracker(update.blockNumber) highestAcceptedFinalizationTracker(update.blockNumber)
} },
) )
.forEach { (handlerName, handler) -> .forEach { (handlerName, handler) ->
l1FinalizationMonitor.addFinalizationHandler(handlerName, handler) l1FinalizationMonitor.addFinalizationHandler(handlerName, handler)
@@ -984,7 +984,7 @@ class L1DependentApp(
lastConsecutiveAggregatedBlockNumber = lastConsecutiveAggregatedBlockNumber, lastConsecutiveAggregatedBlockNumber = lastConsecutiveAggregatedBlockNumber,
batchesRepository = batchesRepository, batchesRepository = batchesRepository,
blobsRepository = blobsRepository, blobsRepository = blobsRepository,
aggregationsRepository = aggregationsRepository aggregationsRepository = aggregationsRepository,
) )
.thenCompose { l1FinalizationMonitor.start() } .thenCompose { l1FinalizationMonitor.start() }
.thenCompose { l1FinalizationHandlerForShomeiRpc.start() } .thenCompose { l1FinalizationHandlerForShomeiRpc.start() }
@@ -1016,7 +1016,7 @@ class L1DependentApp(
blockCreationMonitor.stop(), blockCreationMonitor.stop(),
deadlineConflationCalculatorRunnerOld.stop(), deadlineConflationCalculatorRunnerOld.stop(),
deadlineConflationCalculatorRunnerNew.stop(), deadlineConflationCalculatorRunnerNew.stop(),
blobCompressionProofCoordinator.stop() blobCompressionProofCoordinator.stop(),
) )
.thenCompose { SafeFuture.fromRunnable { l1Web3jClient.shutdown() } } .thenCompose { SafeFuture.fromRunnable { l1Web3jClient.shutdown() } }
.thenApply { log.info("L1App Stopped") } .thenApply { log.info("L1App Stopped") }
@@ -1029,7 +1029,7 @@ class L1DependentApp(
lastConsecutiveAggregatedBlockNumber: ULong, lastConsecutiveAggregatedBlockNumber: ULong,
batchesRepository: BatchesRepository, batchesRepository: BatchesRepository,
blobsRepository: BlobsRepository, blobsRepository: BlobsRepository,
aggregationsRepository: AggregationsRepository aggregationsRepository: AggregationsRepository,
): SafeFuture<*> { ): SafeFuture<*> {
val blockNumberInclusiveToDeleteFrom = lastProcessedBlockNumber + 1u val blockNumberInclusiveToDeleteFrom = lastProcessedBlockNumber + 1u
val cleanupBatches = batchesRepository.deleteBatchesAfterBlockNumber(blockNumberInclusiveToDeleteFrom.toLong()) val cleanupBatches = batchesRepository.deleteBatchesAfterBlockNumber(blockNumberInclusiveToDeleteFrom.toLong())
@@ -1046,7 +1046,7 @@ class L1DependentApp(
*/ */
fun resumeConflationFrom( fun resumeConflationFrom(
aggregationsRepository: AggregationsRepository, aggregationsRepository: AggregationsRepository,
lastFinalizedBlock: ULong lastFinalizedBlock: ULong,
): SafeFuture<ULong> { ): SafeFuture<ULong> {
return aggregationsRepository return aggregationsRepository
.findConsecutiveProvenBlobs(lastFinalizedBlock.toLong() + 1) .findConsecutiveProvenBlobs(lastFinalizedBlock.toLong() + 1)
@@ -1061,7 +1061,7 @@ class L1DependentApp(
fun resumeAggregationFrom( fun resumeAggregationFrom(
aggregationsRepository: AggregationsRepository, aggregationsRepository: AggregationsRepository,
lastFinalizedBlock: ULong lastFinalizedBlock: ULong,
): SafeFuture<ULong> { ): SafeFuture<ULong> {
return aggregationsRepository return aggregationsRepository
.findHighestConsecutiveEndBlockNumber(lastFinalizedBlock.toLong() + 1) .findHighestConsecutiveEndBlockNumber(lastFinalizedBlock.toLong() + 1)
@@ -1075,7 +1075,7 @@ class L1DependentApp(
httpJsonRpcClientFactory: VertxHttpJsonRpcClientFactory, httpJsonRpcClientFactory: VertxHttpJsonRpcClientFactory,
lineaRollupClient: LineaRollupSmartContractClientReadOnly, lineaRollupClient: LineaRollupSmartContractClientReadOnly,
l2Web3jClient: Web3j, l2Web3jClient: Web3j,
vertx: Vertx vertx: Vertx,
): LongRunningService { ): LongRunningService {
if (type2StateProofProviderConfig == null || if (type2StateProofProviderConfig == null ||
type2StateProofProviderConfig.disabled || type2StateProofProviderConfig.disabled ||
@@ -1091,7 +1091,7 @@ class L1DependentApp(
vertx = vertx, vertx = vertx,
rpcClient = httpJsonRpcClientFactory.create(it, log = log), rpcClient = httpJsonRpcClientFactory.create(it, log = log),
retryConfig = type2StateProofProviderConfig.requestRetryConfig, retryConfig = type2StateProofProviderConfig.requestRetryConfig,
log = log log = log,
) )
} }
@@ -1103,16 +1103,16 @@ class L1DependentApp(
config = config =
FinalizationMonitorImpl.Config( FinalizationMonitorImpl.Config(
pollingInterval = type2StateProofProviderConfig.l1PollingInterval.toKotlinDuration(), pollingInterval = type2StateProofProviderConfig.l1PollingInterval.toKotlinDuration(),
l1QueryBlockTag = type2StateProofProviderConfig.l1QueryBlockTag l1QueryBlockTag = type2StateProofProviderConfig.l1QueryBlockTag,
), ),
contract = lineaRollupClient, contract = lineaRollupClient,
l2Client = l2Web3jClient, l2Client = l2Web3jClient,
vertx = vertx vertx = vertx,
) )
l1FinalizationMonitor.addFinalizationHandler("type 2 state proof provider finalization updates", { l1FinalizationMonitor.addFinalizationHandler("type 2 state proof provider finalization updates", {
finalizedBlockNotifier.updateFinalizedBlock( finalizedBlockNotifier.updateFinalizedBlock(
BlockNumberAndHash(it.blockNumber, it.blockHash.toArray()) BlockNumberAndHash(it.blockNumber, it.blockHash.toArray()),
) )
}) })

View File

@@ -28,12 +28,12 @@ class L2NetworkGasPricingService(
httpJsonRpcClientFactory: VertxHttpJsonRpcClientFactory, httpJsonRpcClientFactory: VertxHttpJsonRpcClientFactory,
l1Web3jClient: Web3j, l1Web3jClient: Web3j,
l1Web3jService: Web3jBlobExtended, l1Web3jService: Web3jBlobExtended,
config: Config config: Config,
) : LongRunningService { ) : LongRunningService {
data class LegacyGasPricingCalculatorConfig( data class LegacyGasPricingCalculatorConfig(
val transactionCostCalculatorConfig: TransactionCostCalculator.Config?, val transactionCostCalculatorConfig: TransactionCostCalculator.Config?,
val naiveGasPricingCalculatorConfig: GasUsageRatioWeightedAverageFeesCalculator.Config?, val naiveGasPricingCalculatorConfig: GasUsageRatioWeightedAverageFeesCalculator.Config?,
val legacyGasPricingCalculatorBounds: BoundableFeeCalculator.Config val legacyGasPricingCalculatorBounds: BoundableFeeCalculator.Config,
) )
data class Config( data class Config(
@@ -46,23 +46,23 @@ class L2NetworkGasPricingService(
val variableFeesCalculatorConfig: VariableFeesCalculator.Config, val variableFeesCalculatorConfig: VariableFeesCalculator.Config,
val variableFeesCalculatorBounds: BoundableFeeCalculator.Config, val variableFeesCalculatorBounds: BoundableFeeCalculator.Config,
val extraDataCalculatorConfig: MinerExtraDataV1CalculatorImpl.Config, val extraDataCalculatorConfig: MinerExtraDataV1CalculatorImpl.Config,
val extraDataUpdaterConfig: ExtraDataV1UpdaterImpl.Config val extraDataUpdaterConfig: ExtraDataV1UpdaterImpl.Config,
) )
private val log = LogManager.getLogger(this::class.java) private val log = LogManager.getLogger(this::class.java)
private val gasPricingFeesFetcher: FeesFetcher = FeeHistoryFetcherImpl( private val gasPricingFeesFetcher: FeesFetcher = FeeHistoryFetcherImpl(
l1Web3jClient, l1Web3jClient,
l1Web3jService, l1Web3jService,
config.feeHistoryFetcherConfig config.feeHistoryFetcherConfig,
) )
private val boundedVariableCostCalculator = run { private val boundedVariableCostCalculator = run {
val variableCostCalculator = VariableFeesCalculator( val variableCostCalculator = VariableFeesCalculator(
config.variableFeesCalculatorConfig config.variableFeesCalculatorConfig,
) )
BoundableFeeCalculator( BoundableFeeCalculator(
config = config.variableFeesCalculatorBounds, config = config.variableFeesCalculatorBounds,
feesCalculator = variableCostCalculator feesCalculator = variableCostCalculator,
) )
} }
@@ -71,12 +71,12 @@ class L2NetworkGasPricingService(
TransactionCostCalculator(boundedVariableCostCalculator, config.legacy.transactionCostCalculatorConfig) TransactionCostCalculator(boundedVariableCostCalculator, config.legacy.transactionCostCalculatorConfig)
} else { } else {
GasUsageRatioWeightedAverageFeesCalculator( GasUsageRatioWeightedAverageFeesCalculator(
config.legacy.naiveGasPricingCalculatorConfig!! config.legacy.naiveGasPricingCalculatorConfig!!,
) )
} }
BoundableFeeCalculator( BoundableFeeCalculator(
config.legacy.legacyGasPricingCalculatorBounds, config.legacy.legacyGasPricingCalculatorBounds,
baseCalculator baseCalculator,
) )
} }
@@ -84,7 +84,7 @@ class L2NetworkGasPricingService(
if (config.jsonRpcGasPriceUpdaterConfig != null) { if (config.jsonRpcGasPriceUpdaterConfig != null) {
val l2SetGasPriceUpdater: GasPriceUpdater = GasPriceUpdaterImpl( val l2SetGasPriceUpdater: GasPriceUpdater = GasPriceUpdaterImpl(
httpJsonRpcClientFactory = httpJsonRpcClientFactory, httpJsonRpcClientFactory = httpJsonRpcClientFactory,
config = config.jsonRpcGasPriceUpdaterConfig config = config.jsonRpcGasPriceUpdaterConfig,
) )
MinMineableFeesPricerService( MinMineableFeesPricerService(
@@ -92,7 +92,7 @@ class L2NetworkGasPricingService(
vertx = vertx, vertx = vertx,
feesFetcher = gasPricingFeesFetcher, feesFetcher = gasPricingFeesFetcher,
feesCalculator = legacyGasPricingCalculator, feesCalculator = legacyGasPricingCalculator,
gasPriceUpdater = l2SetGasPriceUpdater gasPriceUpdater = l2SetGasPriceUpdater,
) )
} else { } else {
null null
@@ -106,12 +106,12 @@ class L2NetworkGasPricingService(
minerExtraDataCalculatorImpl = MinerExtraDataV1CalculatorImpl( minerExtraDataCalculatorImpl = MinerExtraDataV1CalculatorImpl(
config = config.extraDataCalculatorConfig, config = config.extraDataCalculatorConfig,
variableFeesCalculator = boundedVariableCostCalculator, variableFeesCalculator = boundedVariableCostCalculator,
legacyFeesCalculator = legacyGasPricingCalculator legacyFeesCalculator = legacyGasPricingCalculator,
), ),
extraDataUpdater = ExtraDataV1UpdaterImpl( extraDataUpdater = ExtraDataV1UpdaterImpl(
httpJsonRpcClientFactory = httpJsonRpcClientFactory, httpJsonRpcClientFactory = httpJsonRpcClientFactory,
config = config.extraDataUpdaterConfig config = config.extraDataUpdaterConfig,
) ),
) )
} else { } else {
null null
@@ -128,7 +128,7 @@ class L2NetworkGasPricingService(
override fun stop(): CompletableFuture<Unit> { override fun stop(): CompletableFuture<Unit> {
return SafeFuture.allOf( return SafeFuture.allOf(
minMineableFeesPricerService?.stop() ?: SafeFuture.completedFuture(Unit), minMineableFeesPricerService?.stop() ?: SafeFuture.completedFuture(Unit),
extraDataPricerService?.stop() ?: SafeFuture.completedFuture(Unit) extraDataPricerService?.stop() ?: SafeFuture.completedFuture(Unit),
) )
.thenApply { } .thenApply { }
.thenPeek { .thenPeek {

View File

@@ -27,7 +27,7 @@ class L1BasedLastFinalizedBlockProvider(
private val lineaRollupSmartContractClient: LineaRollupSmartContractClientReadOnly, private val lineaRollupSmartContractClient: LineaRollupSmartContractClientReadOnly,
private val consistentNumberOfBlocksOnL1: UInt, private val consistentNumberOfBlocksOnL1: UInt,
private val numberOfRetries: UInt = Int.MAX_VALUE.toUInt(), private val numberOfRetries: UInt = Int.MAX_VALUE.toUInt(),
private val pollingInterval: Duration = 2.seconds private val pollingInterval: Duration = 2.seconds,
) : LastFinalizedBlockProvider { ) : LastFinalizedBlockProvider {
private val log: Logger = LogManager.getLogger(this::class.java) private val log: Logger = LogManager.getLogger(this::class.java)
@@ -42,7 +42,7 @@ class L1BasedLastFinalizedBlockProvider(
"Rollup finalized block updated from {} to {}, waiting {} blocks for confirmation", "Rollup finalized block updated from {} to {}, waiting {} blocks for confirmation",
lastObservedBlock.get(), lastObservedBlock.get(),
lastPolledBlockNumber, lastPolledBlockNumber,
consistentNumberOfBlocksOnL1 consistentNumberOfBlocksOnL1,
) )
numberOfObservations.set(1) numberOfObservations.set(1)
lastObservedBlock.set(lastPolledBlockNumber) lastObservedBlock.set(lastPolledBlockNumber)
@@ -54,10 +54,10 @@ class L1BasedLastFinalizedBlockProvider(
vertx, vertx,
maxRetries = numberOfRetries.toInt(), maxRetries = numberOfRetries.toInt(),
backoffDelay = pollingInterval, backoffDelay = pollingInterval,
stopRetriesPredicate = isConsistentEnough stopRetriesPredicate = isConsistentEnough,
) { ) {
lineaRollupSmartContractClient.finalizedL2BlockNumber( lineaRollupSmartContractClient.finalizedL2BlockNumber(
blockParameter = BlockParameter.Tag.LATEST blockParameter = BlockParameter.Tag.LATEST,
) )
} }
} }

View File

@@ -20,14 +20,14 @@ class BlockParameterDecoder : Decoder<BlockParameter> {
BlockParameter.parse(node.value) BlockParameter.parse(node.value)
}.fold( }.fold(
{ it.valid() }, { it.valid() },
{ ConfigFailure.DecodeError(node, type).invalid() } { ConfigFailure.DecodeError(node, type).invalid() },
) )
is LongNode -> runCatching { is LongNode -> runCatching {
BlockParameter.fromNumber(node.value) BlockParameter.fromNumber(node.value)
}.fold( }.fold(
{ it.valid() }, { it.valid() },
{ ConfigFailure.DecodeError(node, type).invalid() } { ConfigFailure.DecodeError(node, type).invalid() },
) )
else -> ConfigFailure.DecodeError(node, type).invalid() else -> ConfigFailure.DecodeError(node, type).invalid()

View File

@@ -29,7 +29,7 @@ import kotlin.time.toJavaDuration
import kotlin.time.toKotlinDuration import kotlin.time.toKotlinDuration
data class ApiConfig( data class ApiConfig(
val observabilityPort: UInt val observabilityPort: UInt,
) )
data class ConflationConfig( data class ConflationConfig(
@@ -42,7 +42,7 @@ data class ConflationConfig(
private var _smartContractErrors: SmartContractErrors?, private var _smartContractErrors: SmartContractErrors?,
val fetchBlocksLimit: Int, val fetchBlocksLimit: Int,
@ConfigAlias("conflation-target-end-block-numbers") @ConfigAlias("conflation-target-end-block-numbers")
private val _conflationTargetEndBlockNumbers: List<Long> = emptyList() private val _conflationTargetEndBlockNumbers: List<Long> = emptyList(),
) { ) {
init { init {
@@ -84,7 +84,7 @@ data class RequestRetryConfigTomlFriendly(
override val maxRetries: Int? = null, override val maxRetries: Int? = null,
override val timeout: Duration? = null, override val timeout: Duration? = null,
override val backoffDelay: Duration = 1.milliseconds.toJavaDuration(), override val backoffDelay: Duration = 1.milliseconds.toJavaDuration(),
val failuresWarningThreshold: Int = 0 val failuresWarningThreshold: Int = 0,
) : RetryConfig { ) : RetryConfig {
init { init {
maxRetries?.also { maxRetries?.also {
@@ -105,25 +105,25 @@ data class RequestRetryConfigTomlFriendly(
maxRetries = maxRetries?.toUInt(), maxRetries = maxRetries?.toUInt(),
timeout = timeout?.toKotlinDuration(), timeout = timeout?.toKotlinDuration(),
backoffDelay = backoffDelay.toKotlinDuration(), backoffDelay = backoffDelay.toKotlinDuration(),
failuresWarningThreshold = failuresWarningThreshold.toUInt() failuresWarningThreshold = failuresWarningThreshold.toUInt(),
) )
internal val asDomain: linea.domain.RetryConfig = linea.domain.RetryConfig( internal val asDomain: linea.domain.RetryConfig = linea.domain.RetryConfig(
maxRetries = maxRetries?.toUInt(), maxRetries = maxRetries?.toUInt(),
timeout = timeout?.toKotlinDuration(), timeout = timeout?.toKotlinDuration(),
backoffDelay = backoffDelay.toKotlinDuration(), backoffDelay = backoffDelay.toKotlinDuration(),
failuresWarningThreshold = failuresWarningThreshold.toUInt() failuresWarningThreshold = failuresWarningThreshold.toUInt(),
) )
companion object { companion object {
fun endlessRetry( fun endlessRetry(
backoffDelay: Duration, backoffDelay: Duration,
failuresWarningThreshold: Int failuresWarningThreshold: Int,
) = RequestRetryConfigTomlFriendly( ) = RequestRetryConfigTomlFriendly(
maxRetries = null, maxRetries = null,
timeout = null, timeout = null,
backoffDelay = backoffDelay, backoffDelay = backoffDelay,
failuresWarningThreshold = failuresWarningThreshold failuresWarningThreshold = failuresWarningThreshold,
) )
} }
} }
@@ -131,7 +131,7 @@ data class RequestRetryConfigTomlFriendly(
data class PersistenceRetryConfig( data class PersistenceRetryConfig(
override val maxRetries: Int? = null, override val maxRetries: Int? = null,
override val backoffDelay: Duration = 1.seconds.toJavaDuration(), override val backoffDelay: Duration = 1.seconds.toJavaDuration(),
override val timeout: Duration? = 10.minutes.toJavaDuration() override val timeout: Duration? = 10.minutes.toJavaDuration(),
) : RetryConfig ) : RetryConfig
internal interface RequestRetryConfigurable { internal interface RequestRetryConfigurable {
@@ -144,7 +144,7 @@ data class BlobCompressionConfig(
val blobSizeLimit: Int, val blobSizeLimit: Int,
@ConfigAlias("batches-limit") @ConfigAlias("batches-limit")
private val _batchesLimit: Int? = null, private val _batchesLimit: Int? = null,
val handlerPollingInterval: Duration val handlerPollingInterval: Duration,
) { ) {
init { init {
_batchesLimit?.also { _batchesLimit?.also {
@@ -163,7 +163,7 @@ data class AggregationConfig(
val deadlineCheckInterval: Duration, val deadlineCheckInterval: Duration,
val aggregationSizeMultipleOf: Int = 1, val aggregationSizeMultipleOf: Int = 1,
@ConfigAlias("target-end-blocks") @ConfigAlias("target-end-blocks")
private val _targetEndBlocks: List<Long> = emptyList() private val _targetEndBlocks: List<Long> = emptyList(),
) { ) {
val targetEndBlocks: List<ULong> = _targetEndBlocks.map { it.toULong() } val targetEndBlocks: List<ULong> = _targetEndBlocks.map { it.toULong() }
@@ -177,12 +177,12 @@ data class TracesConfig(
val blobCompressorVersion: BlobCompressorVersion, val blobCompressorVersion: BlobCompressorVersion,
val expectedTracesApiVersionV2: String, val expectedTracesApiVersionV2: String,
val countersV2: FunctionalityEndpoint, val countersV2: FunctionalityEndpoint,
val conflationV2: FunctionalityEndpoint val conflationV2: FunctionalityEndpoint,
) { ) {
data class FunctionalityEndpoint( data class FunctionalityEndpoint(
val endpoints: List<URL>, val endpoints: List<URL>,
val requestLimitPerEndpoint: UInt, val requestLimitPerEndpoint: UInt,
override val requestRetry: RequestRetryConfigTomlFriendly override val requestRetry: RequestRetryConfigTomlFriendly,
) : RequestRetryConfigurable { ) : RequestRetryConfigurable {
init { init {
require(requestLimitPerEndpoint > 0u) { "requestLimitPerEndpoint must be greater than 0" } require(requestLimitPerEndpoint > 0u) { "requestLimitPerEndpoint must be greater than 0" }
@@ -194,7 +194,7 @@ data class StateManagerClientConfig(
val version: String, val version: String,
val endpoints: List<URL>, val endpoints: List<URL>,
val requestLimitPerEndpoint: UInt, val requestLimitPerEndpoint: UInt,
override val requestRetry: RequestRetryConfigTomlFriendly override val requestRetry: RequestRetryConfigTomlFriendly,
) : RequestRetryConfigurable { ) : RequestRetryConfigurable {
init { init {
require(requestLimitPerEndpoint > 0u) { "requestLimitPerEndpoint must be greater than 0" } require(requestLimitPerEndpoint > 0u) { "requestLimitPerEndpoint must be greater than 0" }
@@ -210,7 +210,7 @@ data class BlobSubmissionConfig(
val maxBlobsToSubmitPerTick: Int = maxBlobsToReturn, val maxBlobsToSubmitPerTick: Int = maxBlobsToReturn,
val targetBlobsToSendPerTransaction: Int = 9, val targetBlobsToSendPerTransaction: Int = 9,
val useEthEstimateGas: Boolean = false, val useEthEstimateGas: Boolean = false,
override var disabled: Boolean = false override var disabled: Boolean = false,
) : FeatureToggleable { ) : FeatureToggleable {
init { init {
require(maxBlobsToReturn > 0) { "maxBlobsToReturn must be greater than 0" } require(maxBlobsToReturn > 0) { "maxBlobsToReturn must be greater than 0" }
@@ -226,7 +226,7 @@ data class AggregationFinalizationConfig(
val maxAggregationsToFinalizePerTick: Int, val maxAggregationsToFinalizePerTick: Int,
val proofSubmissionDelay: Duration, val proofSubmissionDelay: Duration,
val useEthEstimateGas: Boolean = false, val useEthEstimateGas: Boolean = false,
override var disabled: Boolean = false override var disabled: Boolean = false,
) : FeatureToggleable { ) : FeatureToggleable {
init { init {
require(maxAggregationsToFinalizePerTick > 0) { require(maxAggregationsToFinalizePerTick > 0) {
@@ -243,7 +243,7 @@ data class DatabaseConfig(
val schema: String, val schema: String,
val readPoolSize: Int, val readPoolSize: Int,
val readPipeliningLimit: Int, val readPipeliningLimit: Int,
val transactionalPoolSize: Int val transactionalPoolSize: Int,
) )
data class L1Config( data class L1Config(
@@ -268,7 +268,7 @@ data class L1Config(
val blockTime: Duration = Duration.parse("PT12S"), val blockTime: Duration = Duration.parse("PT12S"),
@ConfigAlias("eth-fee-history-endpoint") private val _ethFeeHistoryEndpoint: URL?, @ConfigAlias("eth-fee-history-endpoint") private val _ethFeeHistoryEndpoint: URL?,
@ConfigAlias("genesis-state-root-hash") private val _genesisStateRootHash: String, @ConfigAlias("genesis-state-root-hash") private val _genesisStateRootHash: String,
@ConfigAlias("genesis-shnarf-v6") private val _genesisShnarfV6: String @ConfigAlias("genesis-shnarf-v6") private val _genesisShnarfV6: String,
) { ) {
val ethFeeHistoryEndpoint: URL val ethFeeHistoryEndpoint: URL
get() = _ethFeeHistoryEndpoint ?: rpcEndpoint get() = _ethFeeHistoryEndpoint ?: rpcEndpoint
@@ -303,7 +303,7 @@ data class L2Config(
val lastHashSearchWindow: UInt, val lastHashSearchWindow: UInt,
val anchoringReceiptPollingInterval: Duration, val anchoringReceiptPollingInterval: Duration,
val maxReceiptRetries: UInt, val maxReceiptRetries: UInt,
val newBlockPollingInterval: Duration val newBlockPollingInterval: Duration,
) { ) {
init { init {
messageServiceAddress.assertIsValidAddress("messageServiceAddress") messageServiceAddress.assertIsValidAddress("messageServiceAddress")
@@ -313,11 +313,11 @@ data class L2Config(
data class SignerConfig( data class SignerConfig(
val type: Type, val type: Type,
val web3signer: Web3SignerConfig?, val web3signer: Web3SignerConfig?,
val web3j: Web3jConfig? val web3j: Web3jConfig?,
) { ) {
enum class Type { enum class Type {
Web3j, Web3j,
Web3Signer Web3Signer,
} }
init { init {
@@ -334,14 +334,14 @@ data class SignerConfig(
} }
data class Web3jConfig( data class Web3jConfig(
val privateKey: Masked val privateKey: Masked,
) )
data class Web3SignerConfig( data class Web3SignerConfig(
val endpoint: String, val endpoint: String,
val maxPoolSize: UInt, val maxPoolSize: UInt,
val keepAlive: Boolean, val keepAlive: Boolean,
val publicKey: String val publicKey: String,
) )
interface FeatureToggleable { interface FeatureToggleable {
@@ -354,7 +354,7 @@ data class L1DynamicGasPriceCapServiceConfig(
val gasPriceCapCalculation: GasPriceCapCalculation, val gasPriceCapCalculation: GasPriceCapCalculation,
val feeHistoryFetcher: FeeHistoryFetcher, val feeHistoryFetcher: FeeHistoryFetcher,
val feeHistoryStorage: FeeHistoryStorage, val feeHistoryStorage: FeeHistoryStorage,
override var disabled: Boolean = false override var disabled: Boolean = false,
) : FeatureToggleable { ) : FeatureToggleable {
data class GasPriceCapCalculation( data class GasPriceCapCalculation(
val adjustmentConstant: UInt, val adjustmentConstant: UInt,
@@ -366,7 +366,7 @@ data class L1DynamicGasPriceCapServiceConfig(
val gasPriceCapsCheckCoefficient: Double, val gasPriceCapsCheckCoefficient: Double,
val historicBaseFeePerBlobGasLowerBound: ULong, val historicBaseFeePerBlobGasLowerBound: ULong,
val historicAvgRewardConstant: ULong?, val historicAvgRewardConstant: ULong?,
val timeOfDayMultipliers: TimeOfDayMultipliers? val timeOfDayMultipliers: TimeOfDayMultipliers?,
) { ) {
init { init {
timeOfDayMultipliers?.also { timeOfDayMultipliers?.also {
@@ -385,7 +385,7 @@ data class L1DynamicGasPriceCapServiceConfig(
require(timeOfDayMultiplier.value > 0.0) { require(timeOfDayMultiplier.value > 0.0) {
throw IllegalStateException( throw IllegalStateException(
"Each multiplier in timeOfDayMultipliers must be greater than 0.0." + "Each multiplier in timeOfDayMultipliers must be greater than 0.0." +
" Key=${timeOfDayMultiplier.key} Value=${timeOfDayMultiplier.value}" " Key=${timeOfDayMultiplier.key} Value=${timeOfDayMultiplier.value}",
) )
} }
} }
@@ -404,7 +404,7 @@ data class L1DynamicGasPriceCapServiceConfig(
} }
data class FeeHistoryStorage( data class FeeHistoryStorage(
val storagePeriod: Duration val storagePeriod: Duration,
) { ) {
init { init {
require(storagePeriod <= MAX_FEE_HISTORIES_STORAGE_PERIOD.toJavaDuration()) { require(storagePeriod <= MAX_FEE_HISTORIES_STORAGE_PERIOD.toJavaDuration()) {
@@ -418,12 +418,12 @@ data class L1DynamicGasPriceCapServiceConfig(
val maxBlockCount: UInt, val maxBlockCount: UInt,
val rewardPercentiles: List<Double>, val rewardPercentiles: List<Double>,
val numOfBlocksBeforeLatest: UInt = 4U, val numOfBlocksBeforeLatest: UInt = 4U,
val endpoint: URL? val endpoint: URL?,
) { ) {
init { init {
require( require(
maxBlockCount > 0U && maxBlockCount > 0U &&
maxBlockCount <= MAX_FEE_HISTORY_BLOCK_COUNT maxBlockCount <= MAX_FEE_HISTORY_BLOCK_COUNT,
) { ) {
"maxBlockCount must be greater than 0 and " + "maxBlockCount must be greater than 0 and " +
"less than or equal to $MAX_FEE_HISTORY_BLOCK_COUNT" "less than or equal to $MAX_FEE_HISTORY_BLOCK_COUNT"
@@ -431,7 +431,7 @@ data class L1DynamicGasPriceCapServiceConfig(
require( require(
rewardPercentiles.isNotEmpty() && rewardPercentiles.isNotEmpty() &&
rewardPercentiles.size <= MAX_REWARD_PERCENTILES_SIZE rewardPercentiles.size <= MAX_REWARD_PERCENTILES_SIZE,
) { ) {
"rewardPercentiles must be a non-empty list with " + "rewardPercentiles must be a non-empty list with " +
"maximum length as $MAX_REWARD_PERCENTILES_SIZE." "maximum length as $MAX_REWARD_PERCENTILES_SIZE."
@@ -459,7 +459,7 @@ data class L1DynamicGasPriceCapServiceConfig(
require( require(
gasPriceCapCalculation.gasFeePercentileWindow gasPriceCapCalculation.gasFeePercentileWindow
>= gasPriceCapCalculation.gasFeePercentileWindowLeeway >= gasPriceCapCalculation.gasFeePercentileWindowLeeway,
) { ) {
"gasFeePercentileWindow must be at least same length as" + "gasFeePercentileWindow must be at least same length as" +
" gasFeePercentileWindowLeeway=${gasPriceCapCalculation.gasFeePercentileWindowLeeway}." + " gasFeePercentileWindowLeeway=${gasPriceCapCalculation.gasFeePercentileWindowLeeway}." +
@@ -483,7 +483,7 @@ data class Type2StateProofProviderConfig(
val endpoints: List<URL>, val endpoints: List<URL>,
val l1QueryBlockTag: BlockParameter.Tag = BlockParameter.Tag.LATEST, val l1QueryBlockTag: BlockParameter.Tag = BlockParameter.Tag.LATEST,
val l1PollingInterval: Duration = Duration.ofSeconds(12), val l1PollingInterval: Duration = Duration.ofSeconds(12),
override val requestRetry: RequestRetryConfigTomlFriendly override val requestRetry: RequestRetryConfigTomlFriendly,
) : FeatureToggleable, RequestRetryConfigurable ) : FeatureToggleable, RequestRetryConfigurable
data class TracesLimitsV2ConfigFile(val tracesLimits: Map<TracingModuleV2, UInt>) data class TracesLimitsV2ConfigFile(val tracesLimits: Map<TracingModuleV2, UInt>)
@@ -515,7 +515,7 @@ data class CoordinatorConfigTomlDto(
val l2NetworkGasPricing: L2NetworkGasPricingTomlDto, val l2NetworkGasPricing: L2NetworkGasPricingTomlDto,
val l1DynamicGasPriceCapService: L1DynamicGasPriceCapServiceConfig, val l1DynamicGasPriceCapService: L1DynamicGasPriceCapServiceConfig,
val testL1Disabled: Boolean = false, val testL1Disabled: Boolean = false,
val prover: ProverConfigTomlDto val prover: ProverConfigTomlDto,
) { ) {
fun reified(): CoordinatorConfig = CoordinatorConfig( fun reified(): CoordinatorConfig = CoordinatorConfig(
l2InclusiveBlockNumberToStopAndFlushAggregation = l2InclusiveBlockNumberToStopAndFlushAggregation, l2InclusiveBlockNumberToStopAndFlushAggregation = l2InclusiveBlockNumberToStopAndFlushAggregation,
@@ -537,13 +537,13 @@ data class CoordinatorConfigTomlDto(
l2Signer = l2Signer, l2Signer = l2Signer,
messageAnchoring = messageAnchoring.reified( messageAnchoring = messageAnchoring.reified(
l1DefaultEndpoint = l1.rpcEndpoint, l1DefaultEndpoint = l1.rpcEndpoint,
l2DefaultEndpoint = l2.rpcEndpoint l2DefaultEndpoint = l2.rpcEndpoint,
), ),
l2NetworkGasPricingService = l2NetworkGasPricingService =
if (testL1Disabled || l2NetworkGasPricing.disabled) null else l2NetworkGasPricing.reified(), if (testL1Disabled || l2NetworkGasPricing.disabled) null else l2NetworkGasPricing.reified(),
l1DynamicGasPriceCapService = l1DynamicGasPriceCapService, l1DynamicGasPriceCapService = l1DynamicGasPriceCapService,
testL1Disabled = testL1Disabled, testL1Disabled = testL1Disabled,
proversConfig = prover.reified() proversConfig = prover.reified(),
) )
} }
@@ -569,7 +569,7 @@ data class CoordinatorConfig(
val l2NetworkGasPricingService: L2NetworkGasPricingService.Config?, val l2NetworkGasPricingService: L2NetworkGasPricingService.Config?,
val l1DynamicGasPriceCapService: L1DynamicGasPriceCapServiceConfig, val l1DynamicGasPriceCapService: L1DynamicGasPriceCapServiceConfig,
val testL1Disabled: Boolean = false, val testL1Disabled: Boolean = false,
val proversConfig: ProversConfig val proversConfig: ProversConfig,
) { ) {
init { init {
if (l2InclusiveBlockNumberToStopAndFlushAggregation != null) { if (l2InclusiveBlockNumberToStopAndFlushAggregation != null) {
@@ -583,7 +583,7 @@ data class CoordinatorConfig(
require( require(
blobCompression.batchesLimit == null || blobCompression.batchesLimit == null ||
blobCompression.batchesLimit!! < proofAggregation.aggregationProofsLimit.toUInt() blobCompression.batchesLimit!! < proofAggregation.aggregationProofsLimit.toUInt(),
) { ) {
"[blob-compression].batchesLimit=${blobCompression.batchesLimit} must be less than " + "[blob-compression].batchesLimit=${blobCompression.batchesLimit} must be less than " +
"[proof-aggregation].aggregationProofsLimit=${proofAggregation.aggregationProofsLimit}" "[proof-aggregation].aggregationProofsLimit=${proofAggregation.aggregationProofsLimit}"

View File

@@ -19,7 +19,7 @@ import kotlin.time.toKotlinDuration
data class SampleTransactionGasPricingTomlDto( data class SampleTransactionGasPricingTomlDto(
val plainTransferCostMultiplier: Double = 1.0, val plainTransferCostMultiplier: Double = 1.0,
val compressedTxSize: Int = 125, val compressedTxSize: Int = 125,
val expectedGas: Int = 21000 val expectedGas: Int = 21000,
) )
data class LegacyGasPricingTomlDto( data class LegacyGasPricingTomlDto(
@@ -28,11 +28,11 @@ data class LegacyGasPricingTomlDto(
val naiveGasPricing: NaiveGasPricingTomlDto?, val naiveGasPricing: NaiveGasPricingTomlDto?,
val sampleTransactionGasPricing: SampleTransactionGasPricingTomlDto = SampleTransactionGasPricingTomlDto(), val sampleTransactionGasPricing: SampleTransactionGasPricingTomlDto = SampleTransactionGasPricingTomlDto(),
val gasPriceUpperBound: ULong, val gasPriceUpperBound: ULong,
val gasPriceLowerBound: ULong val gasPriceLowerBound: ULong,
) { ) {
enum class Type { enum class Type {
Naive, Naive,
SampleTransaction SampleTransaction,
} }
init { init {
@@ -49,7 +49,7 @@ data class LegacyGasPricingTomlDto(
data class NaiveGasPricingTomlDto( data class NaiveGasPricingTomlDto(
val baseFeeCoefficient: Double, val baseFeeCoefficient: Double,
val priorityFeeCoefficient: Double, val priorityFeeCoefficient: Double,
val baseFeeBlobCoefficient: Double val baseFeeBlobCoefficient: Double,
) )
data class VariableCostPricingTomlDto( data class VariableCostPricingTomlDto(
@@ -57,7 +57,7 @@ data class VariableCostPricingTomlDto(
val legacyFeesMultiplier: Double, val legacyFeesMultiplier: Double,
val margin: Double, val margin: Double,
val variableCostUpperBound: ULong, val variableCostUpperBound: ULong,
val variableCostLowerBound: ULong val variableCostLowerBound: ULong,
) { ) {
init { init {
require(variableCostUpperBound >= variableCostLowerBound) { require(variableCostUpperBound >= variableCostLowerBound) {
@@ -69,7 +69,7 @@ data class VariableCostPricingTomlDto(
data class JsonRpcPricingPropagationTomlDto( data class JsonRpcPricingPropagationTomlDto(
override var disabled: Boolean = false, override var disabled: Boolean = false,
val gethGasPriceUpdateRecipients: List<URL>, val gethGasPriceUpdateRecipients: List<URL>,
val besuGasPriceUpdateRecipients: List<URL> val besuGasPriceUpdateRecipients: List<URL>,
) : FeatureToggleable { ) : FeatureToggleable {
init { init {
require(disabled || (gethGasPriceUpdateRecipients.isNotEmpty() || besuGasPriceUpdateRecipients.isNotEmpty())) { require(disabled || (gethGasPriceUpdateRecipients.isNotEmpty() || besuGasPriceUpdateRecipients.isNotEmpty())) {
@@ -81,7 +81,7 @@ data class JsonRpcPricingPropagationTomlDto(
data class ExtraDataPricingPropagationTomlDto( data class ExtraDataPricingPropagationTomlDto(
override var disabled: Boolean = false, override var disabled: Boolean = false,
val extraDataUpdateRecipient: URL val extraDataUpdateRecipient: URL,
) : FeatureToggleable ) : FeatureToggleable
data class L2NetworkGasPricingTomlDto( data class L2NetworkGasPricingTomlDto(
@@ -99,7 +99,7 @@ data class L2NetworkGasPricingTomlDto(
val legacy: LegacyGasPricingTomlDto, val legacy: LegacyGasPricingTomlDto,
val variableCostPricing: VariableCostPricingTomlDto, val variableCostPricing: VariableCostPricingTomlDto,
val jsonRpcPricingPropagation: JsonRpcPricingPropagationTomlDto?, val jsonRpcPricingPropagation: JsonRpcPricingPropagationTomlDto?,
val extraDataPricingPropagation: ExtraDataPricingPropagationTomlDto val extraDataPricingPropagation: ExtraDataPricingPropagationTomlDto,
) : FeatureToggleable, RequestRetryConfigurable { ) : FeatureToggleable, RequestRetryConfigurable {
init { init {
require(feeHistoryBlockCount > 0) { "feeHistoryBlockCount must be greater than 0" } require(feeHistoryBlockCount > 0) { "feeHistoryBlockCount must be greater than 0" }
@@ -124,13 +124,13 @@ data class L2NetworkGasPricingTomlDto(
priorityFeeCoefficient = legacy.naiveGasPricing.priorityFeeCoefficient, priorityFeeCoefficient = legacy.naiveGasPricing.priorityFeeCoefficient,
baseFeeBlobCoefficient = legacy.naiveGasPricing.baseFeeBlobCoefficient, baseFeeBlobCoefficient = legacy.naiveGasPricing.baseFeeBlobCoefficient,
blobSubmissionExpectedExecutionGas = blobSubmissionExpectedExecutionGas, blobSubmissionExpectedExecutionGas = blobSubmissionExpectedExecutionGas,
expectedBlobGas = l1BlobGas expectedBlobGas = l1BlobGas,
), ),
legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config( legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config(
legacy.gasPriceUpperBound.toDouble(), legacy.gasPriceUpperBound.toDouble(),
legacy.gasPriceLowerBound.toDouble(), legacy.gasPriceLowerBound.toDouble(),
0.0 0.0,
) ),
) )
} }
@@ -140,14 +140,14 @@ data class L2NetworkGasPricingTomlDto(
sampleTransactionCostMultiplier = legacy.sampleTransactionGasPricing.plainTransferCostMultiplier, sampleTransactionCostMultiplier = legacy.sampleTransactionGasPricing.plainTransferCostMultiplier,
fixedCostWei = variableCostPricing.gasPriceFixedCost, fixedCostWei = variableCostPricing.gasPriceFixedCost,
compressedTxSize = legacy.sampleTransactionGasPricing.compressedTxSize, compressedTxSize = legacy.sampleTransactionGasPricing.compressedTxSize,
expectedGas = legacy.sampleTransactionGasPricing.expectedGas expectedGas = legacy.sampleTransactionGasPricing.expectedGas,
), ),
naiveGasPricingCalculatorConfig = null, naiveGasPricingCalculatorConfig = null,
legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config( legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config(
legacy.gasPriceUpperBound.toDouble(), legacy.gasPriceUpperBound.toDouble(),
legacy.gasPriceLowerBound.toDouble(), legacy.gasPriceLowerBound.toDouble(),
0.0 0.0,
) ),
) )
} }
} }
@@ -155,7 +155,7 @@ data class L2NetworkGasPricingTomlDto(
GasPriceUpdaterImpl.Config( GasPriceUpdaterImpl.Config(
gethEndpoints = jsonRpcPricingPropagation.gethGasPriceUpdateRecipients, gethEndpoints = jsonRpcPricingPropagation.gethGasPriceUpdateRecipients,
besuEndPoints = jsonRpcPricingPropagation.besuGasPriceUpdateRecipients, besuEndPoints = jsonRpcPricingPropagation.besuGasPriceUpdateRecipients,
retryConfig = requestRetryConfig retryConfig = requestRetryConfig,
) )
} else { } else {
null null
@@ -163,7 +163,7 @@ data class L2NetworkGasPricingTomlDto(
return L2NetworkGasPricingService.Config( return L2NetworkGasPricingService.Config(
feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config( feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config(
feeHistoryBlockCount = feeHistoryBlockCount.toUInt(), feeHistoryBlockCount = feeHistoryBlockCount.toUInt(),
feeHistoryRewardPercentile = feeHistoryRewardPercentile feeHistoryRewardPercentile = feeHistoryRewardPercentile,
), ),
legacy = legacyGasPricingConfig, legacy = legacyGasPricingConfig,
jsonRpcGasPriceUpdaterConfig = gasPriceUpdaterConfig, jsonRpcGasPriceUpdaterConfig = gasPriceUpdaterConfig,
@@ -174,21 +174,21 @@ data class L2NetworkGasPricingTomlDto(
blobSubmissionExpectedExecutionGas = blobSubmissionExpectedExecutionGas.toUInt(), blobSubmissionExpectedExecutionGas = blobSubmissionExpectedExecutionGas.toUInt(),
bytesPerDataSubmission = l1BlobGas.toUInt(), bytesPerDataSubmission = l1BlobGas.toUInt(),
expectedBlobGas = bytesPerDataSubmission.toUInt(), expectedBlobGas = bytesPerDataSubmission.toUInt(),
margin = variableCostPricing.margin margin = variableCostPricing.margin,
), ),
variableFeesCalculatorBounds = BoundableFeeCalculator.Config( variableFeesCalculatorBounds = BoundableFeeCalculator.Config(
feeUpperBound = variableCostPricing.variableCostUpperBound.toDouble(), feeUpperBound = variableCostPricing.variableCostUpperBound.toDouble(),
feeLowerBound = variableCostPricing.variableCostLowerBound.toDouble(), feeLowerBound = variableCostPricing.variableCostLowerBound.toDouble(),
feeMargin = 0.0 feeMargin = 0.0,
), ),
extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config( extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config(
fixedCostInKWei = variableCostPricing.gasPriceFixedCost.toKWeiUInt(), fixedCostInKWei = variableCostPricing.gasPriceFixedCost.toKWeiUInt(),
ethGasPriceMultiplier = variableCostPricing.legacyFeesMultiplier ethGasPriceMultiplier = variableCostPricing.legacyFeesMultiplier,
), ),
extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config( extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config(
extraDataPricingPropagation.extraDataUpdateRecipient, extraDataPricingPropagation.extraDataUpdateRecipient,
requestRetryConfig requestRetryConfig,
) ),
) )
} }
} }

View File

@@ -14,7 +14,7 @@ data class MessageAnchoringConfigTomlDto(
val l1HighestBlockTag: BlockParameter = BlockParameter.Tag.FINALIZED, val l1HighestBlockTag: BlockParameter = BlockParameter.Tag.FINALIZED,
val l1RequestRetries: RequestRetryConfigTomlFriendly = RequestRetryConfigTomlFriendly.endlessRetry( val l1RequestRetries: RequestRetryConfigTomlFriendly = RequestRetryConfigTomlFriendly.endlessRetry(
backoffDelay = 1.seconds.toJavaDuration(), backoffDelay = 1.seconds.toJavaDuration(),
failuresWarningThreshold = 3 failuresWarningThreshold = 3,
), ),
val l1EventPollingInterval: Duration = 12.seconds.toJavaDuration(), val l1EventPollingInterval: Duration = 12.seconds.toJavaDuration(),
val l1EventPollingTimeout: Duration = 6.seconds.toJavaDuration(), val l1EventPollingTimeout: Duration = 6.seconds.toJavaDuration(),
@@ -24,11 +24,11 @@ data class MessageAnchoringConfigTomlDto(
val l2HighestBlockTag: BlockParameter = BlockParameter.Tag.LATEST, val l2HighestBlockTag: BlockParameter = BlockParameter.Tag.LATEST,
val l2RequestRetries: RequestRetryConfigTomlFriendly = RequestRetryConfigTomlFriendly.endlessRetry( val l2RequestRetries: RequestRetryConfigTomlFriendly = RequestRetryConfigTomlFriendly.endlessRetry(
backoffDelay = 1.seconds.toJavaDuration(), backoffDelay = 1.seconds.toJavaDuration(),
failuresWarningThreshold = 3 failuresWarningThreshold = 3,
), ),
val anchoringTickInterval: Duration = 2.seconds.toJavaDuration(), val anchoringTickInterval: Duration = 2.seconds.toJavaDuration(),
val messageQueueCapacity: Int = 10_000, val messageQueueCapacity: Int = 10_000,
val maxMessagesToAnchorPerL2Transaction: Int = 100 val maxMessagesToAnchorPerL2Transaction: Int = 100,
) { ) {
init { init {
require(messageQueueCapacity > 0) { require(messageQueueCapacity > 0) {
@@ -56,7 +56,7 @@ data class MessageAnchoringConfigTomlDto(
fun reified( fun reified(
l1DefaultEndpoint: URL, l1DefaultEndpoint: URL,
l2DefaultEndpoint: URL l2DefaultEndpoint: URL,
): MessageAnchoringConfig { ): MessageAnchoringConfig {
return MessageAnchoringConfig( return MessageAnchoringConfig(
disabled = disabled, disabled = disabled,
@@ -72,7 +72,7 @@ data class MessageAnchoringConfigTomlDto(
l1EventSearchBlockChunk = l1EventSearchBlockChunk.toUInt(), l1EventSearchBlockChunk = l1EventSearchBlockChunk.toUInt(),
anchoringTickInterval = anchoringTickInterval.toKotlinDuration(), anchoringTickInterval = anchoringTickInterval.toKotlinDuration(),
messageQueueCapacity = messageQueueCapacity.toUInt(), messageQueueCapacity = messageQueueCapacity.toUInt(),
maxMessagesToAnchorPerL2Transaction = maxMessagesToAnchorPerL2Transaction.toUInt() maxMessagesToAnchorPerL2Transaction = maxMessagesToAnchorPerL2Transaction.toUInt(),
) )
} }
} }
@@ -91,5 +91,5 @@ data class MessageAnchoringConfig(
val l1EventSearchBlockChunk: UInt, val l1EventSearchBlockChunk: UInt,
val anchoringTickInterval: kotlin.time.Duration, val anchoringTickInterval: kotlin.time.Duration,
val messageQueueCapacity: UInt, val messageQueueCapacity: UInt,
val maxMessagesToAnchorPerL2Transaction: UInt val maxMessagesToAnchorPerL2Transaction: UInt,
) : FeatureToggleable ) : FeatureToggleable

View File

@@ -19,13 +19,13 @@ data class ProverConfigTomlDto(
val execution: FileSystemTomlDto, val execution: FileSystemTomlDto,
val blobCompression: FileSystemTomlDto, val blobCompression: FileSystemTomlDto,
val proofAggregation: FileSystemTomlDto, val proofAggregation: FileSystemTomlDto,
val new: ProverConfigTomlDto? = null val new: ProverConfigTomlDto? = null,
) { ) {
private fun asProverConfig(): ProverConfig { private fun asProverConfig(): ProverConfig {
return ProverConfig( return ProverConfig(
execution = execution.toDomain(), execution = execution.toDomain(),
blobCompression = blobCompression.toDomain(), blobCompression = blobCompression.toDomain(),
proofAggregation = proofAggregation.toDomain() proofAggregation = proofAggregation.toDomain(),
) )
} }
@@ -56,7 +56,7 @@ data class ProverConfigTomlDto(
return ProversConfig( return ProversConfig(
proverA = this.asProverConfig(), proverA = this.asProverConfig(),
switchBlockNumberInclusive = new?.switchBlockNumberInclusive?.toULong(), switchBlockNumberInclusive = new?.switchBlockNumberInclusive?.toULong(),
proverB = new?.asProverConfig() proverB = new?.asProverConfig(),
) )
} }
} }
@@ -67,7 +67,7 @@ data class FileSystemTomlDto(
internal var fsInprogressRequestWritingSuffix: String?, internal var fsInprogressRequestWritingSuffix: String?,
internal var fsInprogressProvingSuffixPattern: String?, internal var fsInprogressProvingSuffixPattern: String?,
internal var fsPollingInterval: Duration?, internal var fsPollingInterval: Duration?,
internal var fsPollingTimeout: Duration? internal var fsPollingTimeout: Duration?,
) { ) {
internal fun reifyWithRootDefaults(rootConfig: ProverConfigTomlDto) { internal fun reifyWithRootDefaults(rootConfig: ProverConfigTomlDto) {
fsInprogressRequestWritingSuffix = fsInprogressRequestWritingSuffix fsInprogressRequestWritingSuffix = fsInprogressRequestWritingSuffix
@@ -85,7 +85,7 @@ data class FileSystemTomlDto(
inprogressRequestWritingSuffix = fsInprogressRequestWritingSuffix!!, inprogressRequestWritingSuffix = fsInprogressRequestWritingSuffix!!,
inprogressProvingSuffixPattern = fsInprogressProvingSuffixPattern!!, inprogressProvingSuffixPattern = fsInprogressProvingSuffixPattern!!,
pollingInterval = fsPollingInterval!!.toKotlinDuration(), pollingInterval = fsPollingInterval!!.toKotlinDuration(),
pollingTimeout = fsPollingTimeout!!.toKotlinDuration() pollingTimeout = fsPollingTimeout!!.toKotlinDuration(),
) )
} }
} }

View File

@@ -25,18 +25,18 @@ class BlockCreationMonitor(
private val blockCreationListener: BlockCreationListener, private val blockCreationListener: BlockCreationListener,
private val lastProvenBlockNumberProviderAsync: LastProvenBlockNumberProviderAsync, private val lastProvenBlockNumberProviderAsync: LastProvenBlockNumberProviderAsync,
private val config: Config, private val config: Config,
private val log: Logger = LogManager.getLogger(BlockCreationMonitor::class.java) private val log: Logger = LogManager.getLogger(BlockCreationMonitor::class.java),
) : PeriodicPollingService( ) : PeriodicPollingService(
vertx = vertx, vertx = vertx,
pollingIntervalMs = config.pollingInterval.inWholeMilliseconds, pollingIntervalMs = config.pollingInterval.inWholeMilliseconds,
log = log log = log,
) { ) {
data class Config( data class Config(
val pollingInterval: Duration, val pollingInterval: Duration,
val blocksToFinalization: Long, val blocksToFinalization: Long,
val blocksFetchLimit: Long, val blocksFetchLimit: Long,
val startingBlockWaitTimeout: Duration = 14.days, val startingBlockWaitTimeout: Duration = 14.days,
val lastL2BlockNumberToProcessInclusive: ULong? = null val lastL2BlockNumberToProcessInclusive: ULong? = null,
) )
private val _nexBlockNumberToFetch: AtomicLong = AtomicLong(startingBlockNumberExclusive + 1) private val _nexBlockNumberToFetch: AtomicLong = AtomicLong(startingBlockNumberExclusive + 1)
@@ -76,7 +76,7 @@ class BlockCreationMonitor(
log.warn( log.warn(
"Block {} not found yet. Retrying in {}", "Block {} not found yet. Retrying in {}",
startingBlockNumberExclusive, startingBlockNumberExclusive,
config.pollingInterval config.pollingInterval,
) )
false false
} else { } else {
@@ -84,7 +84,7 @@ class BlockCreationMonitor(
expectedParentBlockHash.set(block.hash) expectedParentBlockHash.set(block.hash)
true true
} }
} },
) { ) {
web3j.ethGetBlock(startingBlockNumberExclusive.toBlockParameter()) web3j.ethGetBlock(startingBlockNumberExclusive.toBlockParameter())
} }
@@ -104,7 +104,7 @@ class BlockCreationMonitor(
lastProvenBlockNumber, lastProvenBlockNumber,
_nexBlockNumberToFetch.get(), _nexBlockNumberToFetch.get(),
_nexBlockNumberToFetch.get() - lastProvenBlockNumber, _nexBlockNumberToFetch.get() - lastProvenBlockNumber,
config.blocksFetchLimit config.blocksFetchLimit,
) )
SafeFuture.COMPLETE SafeFuture.COMPLETE
} else if (config.lastL2BlockNumberToProcessInclusive != null && } else if (config.lastL2BlockNumberToProcessInclusive != null &&
@@ -115,7 +115,7 @@ class BlockCreationMonitor(
"All blocks upto and including lastL2BlockNumberInclusiveToProcess={} have been processed. " + "All blocks upto and including lastL2BlockNumberInclusiveToProcess={} have been processed. " +
"nextBlockNumberToFetch={}", "nextBlockNumberToFetch={}",
config.lastL2BlockNumberToProcessInclusive, config.lastL2BlockNumberToProcessInclusive,
nexBlockNumberToFetch nexBlockNumberToFetch,
) )
SafeFuture.COMPLETE SafeFuture.COMPLETE
} else { } else {
@@ -128,7 +128,7 @@ class BlockCreationMonitor(
log.debug( log.debug(
"updating nexBlockNumberToFetch from {} --> {}", "updating nexBlockNumberToFetch from {} --> {}",
_nexBlockNumberToFetch.get(), _nexBlockNumberToFetch.get(),
_nexBlockNumberToFetch.incrementAndGet() _nexBlockNumberToFetch.incrementAndGet(),
) )
expectedParentBlockHash.set(block.hash) expectedParentBlockHash.set(block.hash)
} }
@@ -140,7 +140,7 @@ class BlockCreationMonitor(
block.number, block.number,
block.hash.encodeHex(), block.hash.encodeHex(),
block.parentHash.encodeHex(), block.parentHash.encodeHex(),
expectedParentBlockHash.get().encodeHex() expectedParentBlockHash.get().encodeHex(),
) )
SafeFuture.failedFuture(IllegalStateException("Reorg detected on block ${block.number}")) SafeFuture.failedFuture(IllegalStateException("Reorg detected on block ${block.number}"))
} }
@@ -164,7 +164,7 @@ class BlockCreationMonitor(
.thenApply { .thenApply {
log.debug( log.debug(
"blockCreationListener blockNumber={} resolved with success", "blockCreationListener blockNumber={} resolved with success",
payload.number payload.number,
) )
} }
.whenException { throwable -> .whenException { throwable ->
@@ -172,7 +172,7 @@ class BlockCreationMonitor(
"Failed to notify blockCreationListener: blockNumber={} errorMessage={}", "Failed to notify blockCreationListener: blockNumber={} errorMessage={}",
payload.number, payload.number,
throwable.message, throwable.message,
throwable throwable,
) )
} }
} }
@@ -195,7 +195,7 @@ class BlockCreationMonitor(
"eth_getBlockByNumber({}) failed: errorMessage={}", "eth_getBlockByNumber({}) failed: errorMessage={}",
blockNumber, blockNumber,
it.message, it.message,
it it,
) )
} }
} else { } else {

View File

@@ -12,10 +12,10 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture
class GethCliqueSafeBlockProvider( class GethCliqueSafeBlockProvider(
private val web3j: Web3j, private val web3j: Web3j,
private val config: Config private val config: Config,
) : SafeBlockProvider { ) : SafeBlockProvider {
data class Config( data class Config(
val blocksToFinalization: Long val blocksToFinalization: Long,
) )
override fun getLatestSafeBlock(): SafeFuture<Block> { override fun getLatestSafeBlock(): SafeFuture<Block> {

View File

@@ -15,7 +15,7 @@ interface LastProvenBlockNumberProviderSync {
class BatchesRepoBasedLastProvenBlockNumberProvider( class BatchesRepoBasedLastProvenBlockNumberProvider(
startingBlockNumberExclusive: Long, startingBlockNumberExclusive: Long,
private val batchesRepository: BatchesRepository private val batchesRepository: BatchesRepository,
) : LastProvenBlockNumberProviderAsync, LastProvenBlockNumberProviderSync { ) : LastProvenBlockNumberProviderAsync, LastProvenBlockNumberProviderSync {
private var latestL1FinalizedBlock: AtomicLong = AtomicLong(startingBlockNumberExclusive) private var latestL1FinalizedBlock: AtomicLong = AtomicLong(startingBlockNumberExclusive)
private var lastProvenBlock: AtomicLong = AtomicLong(startingBlockNumberExclusive) private var lastProvenBlock: AtomicLong = AtomicLong(startingBlockNumberExclusive)
@@ -35,7 +35,7 @@ class BatchesRepoBasedLastProvenBlockNumberProvider(
private fun findAndCacheLastProvenBlockNumberFromDb(): SafeFuture<Long> { private fun findAndCacheLastProvenBlockNumberFromDb(): SafeFuture<Long> {
return batchesRepository.findHighestConsecutiveEndBlockNumberFromBlockNumber( return batchesRepository.findHighestConsecutiveEndBlockNumberFromBlockNumber(
latestL1FinalizedBlock.get() + 1 latestL1FinalizedBlock.get() + 1,
).thenApply { ).thenApply {
newValue -> newValue ->
if (newValue != null) { if (newValue != null) {

View File

@@ -3,7 +3,7 @@ package net.consensys.zkevm.ethereum.coordination
import tech.pegasys.teku.infrastructure.async.SafeFuture import tech.pegasys.teku.infrastructure.async.SafeFuture
class SimpleCompositeSafeFutureHandler<T>( class SimpleCompositeSafeFutureHandler<T>(
private val handlers: List<(T) -> SafeFuture<*>> private val handlers: List<(T) -> SafeFuture<*>>,
) : (T) -> SafeFuture<*> { ) : (T) -> SafeFuture<*> {
override fun invoke(arg: T): SafeFuture<Unit> { override fun invoke(arg: T): SafeFuture<Unit> {
val handlingFutures = val handlingFutures =

View File

@@ -8,7 +8,7 @@ import java.util.function.Supplier
class ConsecutiveProvenBlobsProviderWithLastEndBlockNumberTracker( class ConsecutiveProvenBlobsProviderWithLastEndBlockNumberTracker(
private val repository: AggregationsRepository, private val repository: AggregationsRepository,
initialBlockNumber: ULong initialBlockNumber: ULong,
) : ConsecutiveProvenBlobsProvider, Supplier<Number> { ) : ConsecutiveProvenBlobsProvider, Supplier<Number> {
private val cache = AtomicReference(initialBlockNumber) private val cache = AtomicReference(initialBlockNumber)

View File

@@ -6,7 +6,7 @@ import linea.domain.BlockInterval
import tech.pegasys.teku.infrastructure.async.SafeFuture import tech.pegasys.teku.infrastructure.async.SafeFuture
class BlobZkStateProviderImpl( class BlobZkStateProviderImpl(
private val zkStateClient: StateManagerClientV1 private val zkStateClient: StateManagerClientV1,
) : BlobZkStateProvider { ) : BlobZkStateProvider {
override fun getBlobZKState(blockRange: ULongRange): SafeFuture<BlobZkState> { override fun getBlobZKState(blockRange: ULongRange): SafeFuture<BlobZkState> {
return zkStateClient return zkStateClient
@@ -14,7 +14,7 @@ class BlobZkStateProviderImpl(
.thenApply { .thenApply {
BlobZkState( BlobZkState(
parentStateRootHash = it.zkParentStateRootHash, parentStateRootHash = it.zkParentStateRootHash,
finalStateRootHash = it.zkEndStateRootHash finalStateRootHash = it.zkEndStateRootHash,
) )
} }
} }

View File

@@ -17,7 +17,7 @@ class ForkChoiceUpdaterImpl(private val rollupForkChoiceUpdatedClients: List<Rol
log.debug( log.debug(
"Updating finalized block: {}, to {} clients", "Updating finalized block: {}, to {} clients",
finalizedBlockNumberAndHash, finalizedBlockNumberAndHash,
rollupForkChoiceUpdatedClients.size rollupForkChoiceUpdatedClients.size,
) )
val futures: List<SafeFuture<*>> = rollupForkChoiceUpdatedClients.map { rollupForkChoiceUpdatedClient -> val futures: List<SafeFuture<*>> = rollupForkChoiceUpdatedClients.map { rollupForkChoiceUpdatedClient ->
rollupForkChoiceUpdatedClient rollupForkChoiceUpdatedClient

View File

@@ -28,7 +28,7 @@ class L1BasedLastFinalizedBlockProviderTest {
whenever(lineaRollupClient.finalizedL2BlockNumber(eq(BlockParameter.Tag.LATEST))) whenever(lineaRollupClient.finalizedL2BlockNumber(eq(BlockParameter.Tag.LATEST)))
.thenReturn( .thenReturn(
SafeFuture.completedFuture(replies[0]), SafeFuture.completedFuture(replies[0]),
*replies.subList(1, replies.size).map { SafeFuture.completedFuture(it) }.toTypedArray() *replies.subList(1, replies.size).map { SafeFuture.completedFuture(it) }.toTypedArray(),
) )
val resumerCalculator = L1BasedLastFinalizedBlockProvider( val resumerCalculator = L1BasedLastFinalizedBlockProvider(
@@ -36,7 +36,7 @@ class L1BasedLastFinalizedBlockProviderTest {
lineaRollupClient, lineaRollupClient,
consistentNumberOfBlocksOnL1 = 3u, consistentNumberOfBlocksOnL1 = 3u,
numberOfRetries = 50u, numberOfRetries = 50u,
pollingInterval = 10.milliseconds pollingInterval = 10.milliseconds,
) )
assertThat(resumerCalculator.getLastFinalizedBlock().get()).isEqualTo(101.toULong()) assertThat(resumerCalculator.getLastFinalizedBlock().get()).isEqualTo(101.toULong())

View File

@@ -23,7 +23,7 @@ class L1DependentAppTest {
val lastProcessedBlock = val lastProcessedBlock =
L1DependentApp.resumeConflationFrom( L1DependentApp.resumeConflationFrom(
aggregationsRepository, aggregationsRepository,
lastFinalizedBlock lastFinalizedBlock,
).get() ).get()
assertThat(lastProcessedBlock).isEqualTo(lastFinalizedBlock) assertThat(lastProcessedBlock).isEqualTo(lastFinalizedBlock)
verify(aggregationsRepository).findConsecutiveProvenBlobs(lastFinalizedBlock.toLong() + 1) verify(aggregationsRepository).findConsecutiveProvenBlobs(lastFinalizedBlock.toLong() + 1)
@@ -49,12 +49,12 @@ class L1DependentAppTest {
lastConsecutiveAggregatedBlockNumber = lastConsecutiveAggregatedBlockNumber, lastConsecutiveAggregatedBlockNumber = lastConsecutiveAggregatedBlockNumber,
batchesRepository = batchesRepository, batchesRepository = batchesRepository,
blobsRepository = blobsRepository, blobsRepository = blobsRepository,
aggregationsRepository = aggregationsRepository aggregationsRepository = aggregationsRepository,
).get() ).get()
verify(batchesRepository).deleteBatchesAfterBlockNumber((lastProcessedBlock + 1uL).toLong()) verify(batchesRepository).deleteBatchesAfterBlockNumber((lastProcessedBlock + 1uL).toLong())
verify(blobsRepository).deleteBlobsAfterBlockNumber(lastProcessedBlock + 1uL) verify(blobsRepository).deleteBlobsAfterBlockNumber(lastProcessedBlock + 1uL)
verify(aggregationsRepository).deleteAggregationsAfterBlockNumber( verify(aggregationsRepository).deleteAggregationsAfterBlockNumber(
(lastConsecutiveAggregatedBlockNumber + 1uL).toLong() (lastConsecutiveAggregatedBlockNumber + 1uL).toLong(),
) )
} }
} }

View File

@@ -45,9 +45,9 @@ class CoordinatorConfigTest {
_smartContractErrors = mapOf( _smartContractErrors = mapOf(
// L1 Linea Rollup // L1 Linea Rollup
"0f06cd15" to "DataAlreadySubmitted", "0f06cd15" to "DataAlreadySubmitted",
"c01eab56" to "EmptySubmissionData" "c01eab56" to "EmptySubmissionData",
), ),
fetchBlocksLimit = 4000 fetchBlocksLimit = 4000,
) )
private val proversConfig = ProversConfig( private val proversConfig = ProversConfig(
@@ -58,7 +58,7 @@ class CoordinatorConfigTest {
pollingInterval = 1.seconds, pollingInterval = 1.seconds,
pollingTimeout = 10.minutes, pollingTimeout = 10.minutes,
inprogressProvingSuffixPattern = ".*\\.inprogress\\.prover.*", inprogressProvingSuffixPattern = ".*\\.inprogress\\.prover.*",
inprogressRequestWritingSuffix = ".inprogress_coordinator_writing" inprogressRequestWritingSuffix = ".inprogress_coordinator_writing",
), ),
blobCompression = FileBasedProverConfig( blobCompression = FileBasedProverConfig(
requestsDirectory = Path.of("/data/prover/v2/compression/requests"), requestsDirectory = Path.of("/data/prover/v2/compression/requests"),
@@ -66,7 +66,7 @@ class CoordinatorConfigTest {
pollingInterval = 1.seconds, pollingInterval = 1.seconds,
pollingTimeout = 10.minutes, pollingTimeout = 10.minutes,
inprogressProvingSuffixPattern = ".*\\.inprogress\\.prover.*", inprogressProvingSuffixPattern = ".*\\.inprogress\\.prover.*",
inprogressRequestWritingSuffix = ".inprogress_coordinator_writing" inprogressRequestWritingSuffix = ".inprogress_coordinator_writing",
), ),
proofAggregation = FileBasedProverConfig( proofAggregation = FileBasedProverConfig(
requestsDirectory = Path.of("/data/prover/v2/aggregation/requests"), requestsDirectory = Path.of("/data/prover/v2/aggregation/requests"),
@@ -74,24 +74,24 @@ class CoordinatorConfigTest {
pollingInterval = 1.seconds, pollingInterval = 1.seconds,
pollingTimeout = 10.minutes, pollingTimeout = 10.minutes,
inprogressProvingSuffixPattern = ".*\\.inprogress\\.prover.*", inprogressProvingSuffixPattern = ".*\\.inprogress\\.prover.*",
inprogressRequestWritingSuffix = ".inprogress_coordinator_writing" inprogressRequestWritingSuffix = ".inprogress_coordinator_writing",
) ),
), ),
switchBlockNumberInclusive = null, switchBlockNumberInclusive = null,
proverB = null proverB = null,
) )
private val blobCompressionConfig = BlobCompressionConfig( private val blobCompressionConfig = BlobCompressionConfig(
blobSizeLimit = 100 * 1024, blobSizeLimit = 100 * 1024,
handlerPollingInterval = Duration.parse("PT1S"), handlerPollingInterval = Duration.parse("PT1S"),
_batchesLimit = 1 _batchesLimit = 1,
) )
private val aggregationConfig = AggregationConfig( private val aggregationConfig = AggregationConfig(
aggregationProofsLimit = 3, aggregationProofsLimit = 3,
aggregationDeadline = Duration.parse("PT10S"), aggregationDeadline = Duration.parse("PT10S"),
aggregationCoordinatorPollingInterval = Duration.parse("PT2S"), aggregationCoordinatorPollingInterval = Duration.parse("PT2S"),
deadlineCheckInterval = Duration.parse("PT8S") deadlineCheckInterval = Duration.parse("PT8S"),
) )
private val tracesConfig = TracesConfig( private val tracesConfig = TracesConfig(
@@ -103,38 +103,38 @@ class CoordinatorConfigTest {
requestLimitPerEndpoint = 1U, requestLimitPerEndpoint = 1U,
requestRetry = RequestRetryConfigTomlFriendly( requestRetry = RequestRetryConfigTomlFriendly(
backoffDelay = Duration.parse("PT1S"), backoffDelay = Duration.parse("PT1S"),
failuresWarningThreshold = 2 failuresWarningThreshold = 2,
) ),
), ),
countersV2 = TracesConfig.FunctionalityEndpoint( countersV2 = TracesConfig.FunctionalityEndpoint(
endpoints = listOf(URI("http://traces-node:8545/").toURL()), endpoints = listOf(URI("http://traces-node:8545/").toURL()),
requestLimitPerEndpoint = 1U, requestLimitPerEndpoint = 1U,
requestRetry = RequestRetryConfigTomlFriendly( requestRetry = RequestRetryConfigTomlFriendly(
backoffDelay = Duration.parse("PT1S"), backoffDelay = Duration.parse("PT1S"),
failuresWarningThreshold = 2 failuresWarningThreshold = 2,
) ),
) ),
) )
private val type2StateProofProviderConfig = Type2StateProofProviderConfig( private val type2StateProofProviderConfig = Type2StateProofProviderConfig(
endpoints = listOf(URI("http://shomei-frontend:8888/").toURL()), endpoints = listOf(URI("http://shomei-frontend:8888/").toURL()),
requestRetry = RequestRetryConfigTomlFriendly( requestRetry = RequestRetryConfigTomlFriendly(
backoffDelay = Duration.parse("PT1S"), backoffDelay = Duration.parse("PT1S"),
failuresWarningThreshold = 2 failuresWarningThreshold = 2,
), ),
l1QueryBlockTag = BlockParameter.Tag.SAFE, l1QueryBlockTag = BlockParameter.Tag.SAFE,
l1PollingInterval = Duration.parse("PT6S") l1PollingInterval = Duration.parse("PT6S"),
) )
private val stateManagerConfig = StateManagerClientConfig( private val stateManagerConfig = StateManagerClientConfig(
version = "2.3.0", version = "2.3.0",
endpoints = listOf( endpoints = listOf(
URI("http://shomei:8888/").toURL() URI("http://shomei:8888/").toURL(),
), ),
requestLimitPerEndpoint = 2U, requestLimitPerEndpoint = 2U,
requestRetry = RequestRetryConfigTomlFriendly( requestRetry = RequestRetryConfigTomlFriendly(
backoffDelay = Duration.parse("PT2S"), backoffDelay = Duration.parse("PT2S"),
failuresWarningThreshold = 2 failuresWarningThreshold = 2,
) ),
) )
private val blobSubmissionConfig = BlobSubmissionConfig( private val blobSubmissionConfig = BlobSubmissionConfig(
@@ -146,7 +146,7 @@ class CoordinatorConfigTest {
proofSubmissionDelay = Duration.parse("PT1S"), proofSubmissionDelay = Duration.parse("PT1S"),
targetBlobsToSendPerTransaction = 9, targetBlobsToSendPerTransaction = 9,
useEthEstimateGas = false, useEthEstimateGas = false,
disabled = false disabled = false,
) )
private val aggregationFinalizationConfig = AggregationFinalizationConfig( private val aggregationFinalizationConfig = AggregationFinalizationConfig(
@@ -154,7 +154,7 @@ class CoordinatorConfigTest {
maxAggregationsToFinalizePerTick = 1, maxAggregationsToFinalizePerTick = 1,
proofSubmissionDelay = Duration.parse("PT1S"), proofSubmissionDelay = Duration.parse("PT1S"),
useEthEstimateGas = true, useEthEstimateGas = true,
disabled = false disabled = false,
) )
private val databaseConfig = DatabaseConfig( private val databaseConfig = DatabaseConfig(
@@ -165,12 +165,12 @@ class CoordinatorConfigTest {
schema = "linea_coordinator", schema = "linea_coordinator",
readPoolSize = 10, readPoolSize = 10,
readPipeliningLimit = 10, readPipeliningLimit = 10,
transactionalPoolSize = 10 transactionalPoolSize = 10,
) )
private val persistenceRetryConfig = PersistenceRetryConfig( private val persistenceRetryConfig = PersistenceRetryConfig(
maxRetries = null, maxRetries = null,
backoffDelay = Duration.parse("PT1S") backoffDelay = Duration.parse("PT1S"),
) )
private val l1Config = L1Config( private val l1Config = L1Config(
@@ -194,7 +194,7 @@ class CoordinatorConfigTest {
blockRangeLoopLimit = 500U, blockRangeLoopLimit = 500U,
_ethFeeHistoryEndpoint = null, _ethFeeHistoryEndpoint = null,
_genesisStateRootHash = "0x072ead6777750dc20232d1cee8dc9a395c2d350df4bbaa5096c6f59b214dcecd", _genesisStateRootHash = "0x072ead6777750dc20232d1cee8dc9a395c2d350df4bbaa5096c6f59b214dcecd",
_genesisShnarfV6 = "0x47452a1b9ebadfe02bdd02f580fa1eba17680d57eec968a591644d05d78ee84f" _genesisShnarfV6 = "0x47452a1b9ebadfe02bdd02f580fa1eba17680d57eec968a591644d05d78ee84f",
) )
private val l2Config = L2Config( private val l2Config = L2Config(
@@ -208,7 +208,7 @@ class CoordinatorConfigTest {
lastHashSearchWindow = 25U, lastHashSearchWindow = 25U,
anchoringReceiptPollingInterval = Duration.parse("PT01S"), anchoringReceiptPollingInterval = Duration.parse("PT01S"),
maxReceiptRetries = 120U, maxReceiptRetries = 120U,
newBlockPollingInterval = Duration.parse("PT1S") newBlockPollingInterval = Duration.parse("PT1S"),
) )
private val finalizationSigner = SignerConfig( private val finalizationSigner = SignerConfig(
@@ -219,9 +219,9 @@ class CoordinatorConfigTest {
keepAlive = true, keepAlive = true,
publicKey = publicKey =
"ba5734d8f7091719471e7f7ed6b9df170dc70cc661ca05e688601ad984f068b0d67351e5f06073092499336ab0839ef8a521afd334e5" + "ba5734d8f7091719471e7f7ed6b9df170dc70cc661ca05e688601ad984f068b0d67351e5f06073092499336ab0839ef8a521afd334e5" +
"3807205fa2f08eec74f4" "3807205fa2f08eec74f4",
), ),
web3j = Web3jConfig(Masked("0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d")) web3j = Web3jConfig(Masked("0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d")),
) )
private val dataSubmissionSigner = SignerConfig( private val dataSubmissionSigner = SignerConfig(
@@ -232,9 +232,9 @@ class CoordinatorConfigTest {
keepAlive = true, keepAlive = true,
publicKey = publicKey =
"9d9031e97dd78ff8c15aa86939de9b1e791066a0224e331bc962a2099a7b1f0464b8bbafe1535f2301c72c2cb3535b172da30b02686a" + "9d9031e97dd78ff8c15aa86939de9b1e791066a0224e331bc962a2099a7b1f0464b8bbafe1535f2301c72c2cb3535b172da30b02686a" +
"b0393d348614f157fbdb" "b0393d348614f157fbdb",
), ),
web3j = Web3jConfig(Masked("0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a")) web3j = Web3jConfig(Masked("0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a")),
) )
private val l2SignerConfig = SignerConfig( private val l2SignerConfig = SignerConfig(
type = SignerConfig.Type.Web3j, type = SignerConfig.Type.Web3j,
@@ -244,43 +244,43 @@ class CoordinatorConfigTest {
keepAlive = true, keepAlive = true,
publicKey = publicKey =
"4a788ad6fa008beed58de6418369717d7492f37d173d70e2c26d9737e2c6eeae929452ef8602a19410844db3e200a0e73f5208fd7625" + "4a788ad6fa008beed58de6418369717d7492f37d173d70e2c26d9737e2c6eeae929452ef8602a19410844db3e200a0e73f5208fd7625" +
"9a8766b73953fc3e7023" "9a8766b73953fc3e7023",
), ),
web3j = Web3jConfig(Masked("0x4d01ae6487860981699236a58b68f807ee5f17b12df5740b85cf4c4653be0f55")) web3j = Web3jConfig(Masked("0x4d01ae6487860981699236a58b68f807ee5f17b12df5740b85cf4c4653be0f55")),
) )
private val l2NetworkGasPricingRequestRetryConfig = RequestRetryConfig( private val l2NetworkGasPricingRequestRetryConfig = RequestRetryConfig(
maxRetries = 3u, maxRetries = 3u,
timeout = 6.seconds, timeout = 6.seconds,
backoffDelay = 1.seconds, backoffDelay = 1.seconds,
failuresWarningThreshold = 2u failuresWarningThreshold = 2u,
) )
private val l2NetworkGasPricingServiceConfig = L2NetworkGasPricingService.Config( private val l2NetworkGasPricingServiceConfig = L2NetworkGasPricingService.Config(
feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config( feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config(
feeHistoryBlockCount = 50U, feeHistoryBlockCount = 50U,
feeHistoryRewardPercentile = 15.0 feeHistoryRewardPercentile = 15.0,
), ),
legacy = L2NetworkGasPricingService.LegacyGasPricingCalculatorConfig( legacy = L2NetworkGasPricingService.LegacyGasPricingCalculatorConfig(
legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config( legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config(
feeUpperBound = 10_000_000_000.0, feeUpperBound = 10_000_000_000.0,
feeLowerBound = 90_000_000.0, feeLowerBound = 90_000_000.0,
feeMargin = 0.0 feeMargin = 0.0,
), ),
transactionCostCalculatorConfig = TransactionCostCalculator.Config( transactionCostCalculatorConfig = TransactionCostCalculator.Config(
sampleTransactionCostMultiplier = 1.0, sampleTransactionCostMultiplier = 1.0,
fixedCostWei = 3000000u, fixedCostWei = 3000000u,
compressedTxSize = 125, compressedTxSize = 125,
expectedGas = 21000 expectedGas = 21000,
), ),
naiveGasPricingCalculatorConfig = null naiveGasPricingCalculatorConfig = null,
), ),
jsonRpcGasPriceUpdaterConfig = GasPriceUpdaterImpl.Config( jsonRpcGasPriceUpdaterConfig = GasPriceUpdaterImpl.Config(
gethEndpoints = listOf( gethEndpoints = listOf(
URI("http://l2-node:8545/").toURL() URI("http://l2-node:8545/").toURL(),
), ),
besuEndPoints = listOf(), besuEndPoints = listOf(),
retryConfig = l2NetworkGasPricingRequestRetryConfig retryConfig = l2NetworkGasPricingRequestRetryConfig,
), ),
jsonRpcPriceUpdateInterval = 12.seconds, jsonRpcPriceUpdateInterval = 12.seconds,
extraDataPricingPropagationEnabled = true, extraDataPricingPropagationEnabled = true,
@@ -289,21 +289,21 @@ class CoordinatorConfigTest {
blobSubmissionExpectedExecutionGas = 213_000u, blobSubmissionExpectedExecutionGas = 213_000u,
bytesPerDataSubmission = 131072u, bytesPerDataSubmission = 131072u,
expectedBlobGas = 131072u, expectedBlobGas = 131072u,
margin = 4.0 margin = 4.0,
), ),
variableFeesCalculatorBounds = BoundableFeeCalculator.Config( variableFeesCalculatorBounds = BoundableFeeCalculator.Config(
feeUpperBound = 10_000_000_001.0, feeUpperBound = 10_000_000_001.0,
feeLowerBound = 90_000_001.0, feeLowerBound = 90_000_001.0,
feeMargin = 0.0 feeMargin = 0.0,
), ),
extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config( extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config(
fixedCostInKWei = 3000u, fixedCostInKWei = 3000u,
ethGasPriceMultiplier = 1.2 ethGasPriceMultiplier = 1.2,
), ),
extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config( extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config(
sequencerEndpoint = URI(/* str = */ "http://sequencer:8545/").toURL(), sequencerEndpoint = URI("http://sequencer:8545/").toURL(),
retryConfig = l2NetworkGasPricingRequestRetryConfig retryConfig = l2NetworkGasPricingRequestRetryConfig,
) ),
) )
private val l1DynamicGasPriceCapServiceConfig = L1DynamicGasPriceCapServiceConfig( private val l1DynamicGasPriceCapServiceConfig = L1DynamicGasPriceCapServiceConfig(
@@ -318,18 +318,18 @@ class CoordinatorConfigTest {
gasPriceCapsCheckCoefficient = 0.9, gasPriceCapsCheckCoefficient = 0.9,
historicBaseFeePerBlobGasLowerBound = 100_000_000u, historicBaseFeePerBlobGasLowerBound = 100_000_000u,
historicAvgRewardConstant = 100_000_000u, historicAvgRewardConstant = 100_000_000u,
timeOfDayMultipliers = expectedTimeOfDayMultipliers timeOfDayMultipliers = expectedTimeOfDayMultipliers,
), ),
feeHistoryFetcher = L1DynamicGasPriceCapServiceConfig.FeeHistoryFetcher( feeHistoryFetcher = L1DynamicGasPriceCapServiceConfig.FeeHistoryFetcher(
fetchInterval = Duration.parse("PT1S"), fetchInterval = Duration.parse("PT1S"),
maxBlockCount = 1000U, maxBlockCount = 1000U,
rewardPercentiles = listOf(10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0), rewardPercentiles = listOf(10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0),
numOfBlocksBeforeLatest = 4U, numOfBlocksBeforeLatest = 4U,
endpoint = null endpoint = null,
), ),
feeHistoryStorage = L1DynamicGasPriceCapServiceConfig.FeeHistoryStorage( feeHistoryStorage = L1DynamicGasPriceCapServiceConfig.FeeHistoryStorage(
storagePeriod = Duration.parse("PT2M") storagePeriod = Duration.parse("PT2M"),
) ),
) )
private val coordinatorConfig = CoordinatorConfig( private val coordinatorConfig = CoordinatorConfig(
@@ -351,11 +351,11 @@ class CoordinatorConfigTest {
l2Signer = l2SignerConfig, l2Signer = l2SignerConfig,
messageAnchoring = MessageAnchoringConfigTomlDto().reified( messageAnchoring = MessageAnchoringConfigTomlDto().reified(
l1DefaultEndpoint = l1Config.rpcEndpoint, l1DefaultEndpoint = l1Config.rpcEndpoint,
l2DefaultEndpoint = l2Config.rpcEndpoint l2DefaultEndpoint = l2Config.rpcEndpoint,
), ),
l2NetworkGasPricingService = l2NetworkGasPricingServiceConfig, l2NetworkGasPricingService = l2NetworkGasPricingServiceConfig,
l1DynamicGasPriceCapService = l1DynamicGasPriceCapServiceConfig, l1DynamicGasPriceCapService = l1DynamicGasPriceCapServiceConfig,
proversConfig = proversConfig proversConfig = proversConfig,
) )
} }
@@ -371,18 +371,18 @@ class CoordinatorConfigTest {
Path.of("../../config/coordinator/coordinator-docker-traces-v2-override.config.toml"), Path.of("../../config/coordinator/coordinator-docker-traces-v2-override.config.toml"),
Path.of("../../config/coordinator/coordinator-docker-web3signer-override.config.toml"), Path.of("../../config/coordinator/coordinator-docker-web3signer-override.config.toml"),
Path.of("../../config/coordinator/coordinator-local-dev.config.overrides.toml"), Path.of("../../config/coordinator/coordinator-local-dev.config.overrides.toml"),
Path.of("../../config/coordinator/coordinator-local-dev.config-traces-v2.overrides.toml") Path.of("../../config/coordinator/coordinator-local-dev.config-traces-v2.overrides.toml"),
), ),
tracesLimitsFileV2 = Path.of("../../config/common/traces-limits-v2.toml"), tracesLimitsFileV2 = Path.of("../../config/common/traces-limits-v2.toml"),
gasPriceCapTimeOfDayMultipliersFile = Path.of("../../config/common/gas-price-cap-time-of-day-multipliers.toml"), gasPriceCapTimeOfDayMultipliersFile = Path.of("../../config/common/gas-price-cap-time-of-day-multipliers.toml"),
smartContractErrorsFile = Path.of("../../config/common/smart-contract-errors.toml") smartContractErrorsFile = Path.of("../../config/common/smart-contract-errors.toml"),
) )
} }
private fun pathToResource(resource: String): Path { private fun pathToResource(resource: String): Path {
return Paths.get( return Paths.get(
this::class.java.classLoader.getResource(resource)?.toURI() this::class.java.classLoader.getResource(resource)?.toURI()
?: error("Resource not found: $resource") ?: error("Resource not found: $resource"),
) )
} }
@@ -392,7 +392,7 @@ class CoordinatorConfigTest {
coordinatorConfigFiles = listOf(pathToResource("configs/coordinator.config.toml")), coordinatorConfigFiles = listOf(pathToResource("configs/coordinator.config.toml")),
tracesLimitsFileV2 = pathToResource("configs/traces-limits-v2.toml"), tracesLimitsFileV2 = pathToResource("configs/traces-limits-v2.toml"),
gasPriceCapTimeOfDayMultipliersFile = pathToResource("configs/gas-price-cap-time-of-day-multipliers.toml"), gasPriceCapTimeOfDayMultipliersFile = pathToResource("configs/gas-price-cap-time-of-day-multipliers.toml"),
smartContractErrorsFile = pathToResource("configs/smart-contract-errors.toml") smartContractErrorsFile = pathToResource("configs/smart-contract-errors.toml"),
) )
assertEquals(coordinatorConfig, configs) assertEquals(coordinatorConfig, configs)
@@ -404,18 +404,18 @@ class CoordinatorConfigTest {
val config = loadConfigs( val config = loadConfigs(
coordinatorConfigFiles = listOf( coordinatorConfigFiles = listOf(
pathToResource("configs/coordinator.config.toml"), pathToResource("configs/coordinator.config.toml"),
pathToResource("configs/coordinator-web3signer-override.config.toml") pathToResource("configs/coordinator-web3signer-override.config.toml"),
), ),
tracesLimitsFileV2 = pathToResource("configs/traces-limits-v2.toml"), tracesLimitsFileV2 = pathToResource("configs/traces-limits-v2.toml"),
gasPriceCapTimeOfDayMultipliersFile = pathToResource("configs/gas-price-cap-time-of-day-multipliers.toml"), gasPriceCapTimeOfDayMultipliersFile = pathToResource("configs/gas-price-cap-time-of-day-multipliers.toml"),
smartContractErrorsFile = pathToResource("configs/smart-contract-errors.toml") smartContractErrorsFile = pathToResource("configs/smart-contract-errors.toml"),
) )
val expectedConfig = val expectedConfig =
coordinatorConfig.copy( coordinatorConfig.copy(
finalizationSigner = finalizationSigner.copy(type = SignerConfig.Type.Web3Signer), finalizationSigner = finalizationSigner.copy(type = SignerConfig.Type.Web3Signer),
dataSubmissionSigner = dataSubmissionSigner.copy(type = SignerConfig.Type.Web3Signer), dataSubmissionSigner = dataSubmissionSigner.copy(type = SignerConfig.Type.Web3Signer),
l2Signer = l2SignerConfig.copy(type = SignerConfig.Type.Web3Signer) l2Signer = l2SignerConfig.copy(type = SignerConfig.Type.Web3Signer),
) )
assertThat(config).isEqualTo(expectedConfig) assertThat(config).isEqualTo(expectedConfig)
@@ -426,11 +426,11 @@ class CoordinatorConfigTest {
val config = loadConfigs( val config = loadConfigs(
coordinatorConfigFiles = listOf( coordinatorConfigFiles = listOf(
pathToResource("configs/coordinator.config.toml"), pathToResource("configs/coordinator.config.toml"),
pathToResource("configs/coordinator-traces-v2-override.config.toml") pathToResource("configs/coordinator-traces-v2-override.config.toml"),
), ),
tracesLimitsFileV2 = pathToResource("configs/traces-limits-v2.toml"), tracesLimitsFileV2 = pathToResource("configs/traces-limits-v2.toml"),
gasPriceCapTimeOfDayMultipliersFile = pathToResource("configs/gas-price-cap-time-of-day-multipliers.toml"), gasPriceCapTimeOfDayMultipliersFile = pathToResource("configs/gas-price-cap-time-of-day-multipliers.toml"),
smartContractErrorsFile = pathToResource("configs/smart-contract-errors.toml") smartContractErrorsFile = pathToResource("configs/smart-contract-errors.toml"),
) )
val expectedConfig = val expectedConfig =
@@ -441,31 +441,31 @@ class CoordinatorConfigTest {
transactionCostCalculatorConfig = transactionCostCalculatorConfig =
l2NetworkGasPricingServiceConfig.legacy.transactionCostCalculatorConfig?.copy( l2NetworkGasPricingServiceConfig.legacy.transactionCostCalculatorConfig?.copy(
compressedTxSize = 350, compressedTxSize = 350,
expectedGas = 29400 expectedGas = 29400,
) ),
) ),
), ),
traces = tracesConfig.copy( traces = tracesConfig.copy(
blobCompressorVersion = BlobCompressorVersion.V1_2, blobCompressorVersion = BlobCompressorVersion.V1_2,
expectedTracesApiVersionV2 = "v0.8.0-rc8", expectedTracesApiVersionV2 = "v0.8.0-rc8",
conflationV2 = tracesConfig.conflationV2, conflationV2 = tracesConfig.conflationV2,
countersV2 = tracesConfig.countersV2 countersV2 = tracesConfig.countersV2,
), ),
proversConfig = proversConfig.copy( proversConfig = proversConfig.copy(
proverA = proversConfig.proverA.copy( proverA = proversConfig.proverA.copy(
execution = proversConfig.proverA.execution.copy( execution = proversConfig.proverA.execution.copy(
requestsDirectory = Path.of("/data/prover/v3/execution/requests"), requestsDirectory = Path.of("/data/prover/v3/execution/requests"),
responsesDirectory = Path.of("/data/prover/v3/execution/responses") responsesDirectory = Path.of("/data/prover/v3/execution/responses"),
), ),
blobCompression = proversConfig.proverA.blobCompression.copy( blobCompression = proversConfig.proverA.blobCompression.copy(
requestsDirectory = Path.of("/data/prover/v3/compression/requests"), requestsDirectory = Path.of("/data/prover/v3/compression/requests"),
responsesDirectory = Path.of("/data/prover/v3/compression/responses") responsesDirectory = Path.of("/data/prover/v3/compression/responses"),
), ),
proofAggregation = proversConfig.proverA.proofAggregation.copy( proofAggregation = proversConfig.proverA.proofAggregation.copy(
requestsDirectory = Path.of("/data/prover/v3/aggregation/requests"), requestsDirectory = Path.of("/data/prover/v3/aggregation/requests"),
responsesDirectory = Path.of("/data/prover/v3/aggregation/responses") responsesDirectory = Path.of("/data/prover/v3/aggregation/responses"),
) ),
) ),
), ),
messageAnchoring = MessageAnchoringConfigTomlDto().copy( messageAnchoring = MessageAnchoringConfigTomlDto().copy(
l1Endpoint = URI("http://l1-endpoint-for-anchoring:8545").toURL(), l1Endpoint = URI("http://l1-endpoint-for-anchoring:8545").toURL(),
@@ -475,12 +475,12 @@ class CoordinatorConfigTest {
anchoringTickInterval = 1.seconds.toJavaDuration(), anchoringTickInterval = 1.seconds.toJavaDuration(),
l1RequestRetries = RequestRetryConfigTomlFriendly( l1RequestRetries = RequestRetryConfigTomlFriendly(
maxRetries = 10, maxRetries = 10,
failuresWarningThreshold = 1 failuresWarningThreshold = 1,
) ),
).reified( ).reified(
l1DefaultEndpoint = l1Config.rpcEndpoint, l1DefaultEndpoint = l1Config.rpcEndpoint,
l2DefaultEndpoint = l2Config.rpcEndpoint l2DefaultEndpoint = l2Config.rpcEndpoint,
) ),
) )
assertThat(config).isEqualTo(expectedConfig) assertThat(config).isEqualTo(expectedConfig)
@@ -489,7 +489,7 @@ class CoordinatorConfigTest {
@Test @Test
fun invalidConfigReturnsErrorResult() { fun invalidConfigReturnsErrorResult() {
val configsResult = loadConfigsOrError<TestConfig>( val configsResult = loadConfigsOrError<TestConfig>(
configFiles = listOf(pathToResource("configs/coordinator.config.toml")) configFiles = listOf(pathToResource("configs/coordinator.config.toml")),
) )
assertThat(configsResult.getError()).contains("'extraField': Missing String from config") assertThat(configsResult.getError()).contains("'extraField': Missing String from config")
@@ -498,17 +498,17 @@ class CoordinatorConfigTest {
@Test @Test
fun testInvalidAggregationByTargetBlockNumberWhenL2InclusiveBlockNumberToStopAndFlushAggregationSpecified() { fun testInvalidAggregationByTargetBlockNumberWhenL2InclusiveBlockNumberToStopAndFlushAggregationSpecified() {
val aggregationConfigWithoutTargetBlockNumber = aggregationConfig.copy( val aggregationConfigWithoutTargetBlockNumber = aggregationConfig.copy(
_targetEndBlocks = emptyList() _targetEndBlocks = emptyList(),
) )
val conflationConfigWithTargetBlockNumber = conflationConfig.copy( val conflationConfigWithTargetBlockNumber = conflationConfig.copy(
_conflationTargetEndBlockNumbers = listOf(100L) _conflationTargetEndBlockNumbers = listOf(100L),
) )
val exception = assertThrows<IllegalArgumentException> { val exception = assertThrows<IllegalArgumentException> {
coordinatorConfig.copy( coordinatorConfig.copy(
l2InclusiveBlockNumberToStopAndFlushAggregation = 100uL, l2InclusiveBlockNumberToStopAndFlushAggregation = 100uL,
proofAggregation = aggregationConfigWithoutTargetBlockNumber, proofAggregation = aggregationConfigWithoutTargetBlockNumber,
conflation = conflationConfigWithTargetBlockNumber conflation = conflationConfigWithTargetBlockNumber,
) )
} }
assertThat(exception.message) assertThat(exception.message)
@@ -518,40 +518,40 @@ class CoordinatorConfigTest {
@Test @Test
fun testInvalidConflationByTargetBlockNumberWhenL2InclusiveBlockNumberToStopAndFlushAggregationSpecified() { fun testInvalidConflationByTargetBlockNumberWhenL2InclusiveBlockNumberToStopAndFlushAggregationSpecified() {
val aggregationConfigWithTargetBlockNumber = aggregationConfig.copy( val aggregationConfigWithTargetBlockNumber = aggregationConfig.copy(
_targetEndBlocks = listOf(100L) _targetEndBlocks = listOf(100L),
) )
val conflationConfigWithoutTargetBlockNumber = conflationConfig.copy( val conflationConfigWithoutTargetBlockNumber = conflationConfig.copy(
_conflationTargetEndBlockNumbers = emptyList() _conflationTargetEndBlockNumbers = emptyList(),
) )
val exception = assertThrows<IllegalArgumentException> { val exception = assertThrows<IllegalArgumentException> {
coordinatorConfig.copy( coordinatorConfig.copy(
l2InclusiveBlockNumberToStopAndFlushAggregation = 100uL, l2InclusiveBlockNumberToStopAndFlushAggregation = 100uL,
proofAggregation = aggregationConfigWithTargetBlockNumber, proofAggregation = aggregationConfigWithTargetBlockNumber,
conflation = conflationConfigWithoutTargetBlockNumber conflation = conflationConfigWithoutTargetBlockNumber,
) )
} }
assertThat(exception.message) assertThat(exception.message)
.isEqualTo( .isEqualTo(
"conflation.conflationTargetEndBlockNumbers should contain the " + "conflation.conflationTargetEndBlockNumbers should contain the " +
"l2InclusiveBlockNumberToStopAndFlushAggregation" "l2InclusiveBlockNumberToStopAndFlushAggregation",
) )
} }
@Test @Test
fun testValidAggrAndConflationByTargetBlockNumberWhenL2InclusiveBlockNumberToStopAndFlushAggregationSpecified() { fun testValidAggrAndConflationByTargetBlockNumberWhenL2InclusiveBlockNumberToStopAndFlushAggregationSpecified() {
val aggregationConfigWithoutSwithBlockNumber = aggregationConfig.copy( val aggregationConfigWithoutSwithBlockNumber = aggregationConfig.copy(
_targetEndBlocks = listOf(10L, 100L) _targetEndBlocks = listOf(10L, 100L),
) )
val conflationConfigWithTargetBlockNumber = conflationConfig.copy( val conflationConfigWithTargetBlockNumber = conflationConfig.copy(
_conflationTargetEndBlockNumbers = listOf(100L) _conflationTargetEndBlockNumbers = listOf(100L),
) )
assertDoesNotThrow { assertDoesNotThrow {
coordinatorConfig.copy( coordinatorConfig.copy(
l2InclusiveBlockNumberToStopAndFlushAggregation = 100uL, l2InclusiveBlockNumberToStopAndFlushAggregation = 100uL,
proofAggregation = aggregationConfigWithoutSwithBlockNumber, proofAggregation = aggregationConfigWithoutSwithBlockNumber,
conflation = conflationConfigWithTargetBlockNumber conflation = conflationConfigWithTargetBlockNumber,
) )
} }
} }

View File

@@ -168,5 +168,5 @@ val expectedTimeOfDayMultipliers = mapOf(
"SATURDAY_20" to 1.5073787902995706, "SATURDAY_20" to 1.5073787902995706,
"SATURDAY_21" to 1.5605139580010123, "SATURDAY_21" to 1.5605139580010123,
"SATURDAY_22" to 1.5885303316932382, "SATURDAY_22" to 1.5885303316932382,
"SATURDAY_23" to 1.6169891066719597 "SATURDAY_23" to 1.6169891066719597,
) )

View File

@@ -55,6 +55,6 @@ val expectedTracesLimitsV2 = TracesCountersV2(
TracingModuleV2.BLOCK_KECCAK to 46u, TracingModuleV2.BLOCK_KECCAK to 46u,
TracingModuleV2.BLOCK_L1_SIZE to 47u, TracingModuleV2.BLOCK_L1_SIZE to 47u,
TracingModuleV2.BLOCK_L2_L1_LOGS to 48u, TracingModuleV2.BLOCK_L2_L1_LOGS to 48u,
TracingModuleV2.BLOCK_TRANSACTIONS to 49u TracingModuleV2.BLOCK_TRANSACTIONS to 49u,
) ),
) )

View File

@@ -21,7 +21,7 @@ import kotlin.time.toJavaDuration
class L2NetworkGasPricingConfigTest { class L2NetworkGasPricingConfigTest {
data class Config( data class Config(
val l2NetworkGasPricing: L2NetworkGasPricingTomlDto val l2NetworkGasPricing: L2NetworkGasPricingTomlDto,
) )
private fun parseConfig(toml: String): L2NetworkGasPricingTomlDto { private fun parseConfig(toml: String): L2NetworkGasPricingTomlDto {
@@ -135,7 +135,7 @@ class L2NetworkGasPricingConfigTest {
maxRetries = 3, maxRetries = 3,
timeout = 6.seconds.toJavaDuration(), timeout = 6.seconds.toJavaDuration(),
backoffDelay = 1.seconds.toJavaDuration(), backoffDelay = 1.seconds.toJavaDuration(),
failuresWarningThreshold = 2 failuresWarningThreshold = 2,
), ),
priceUpdateInterval = Duration.parse("PT12S"), priceUpdateInterval = Duration.parse("PT12S"),
@@ -152,29 +152,29 @@ class L2NetworkGasPricingConfigTest {
naiveGasPricing = NaiveGasPricingTomlDto( naiveGasPricing = NaiveGasPricingTomlDto(
baseFeeCoefficient = 0.1, baseFeeCoefficient = 0.1,
priorityFeeCoefficient = 1.0, priorityFeeCoefficient = 1.0,
baseFeeBlobCoefficient = 0.1 baseFeeBlobCoefficient = 0.1,
) ),
), ),
variableCostPricing = VariableCostPricingTomlDto( variableCostPricing = VariableCostPricingTomlDto(
gasPriceFixedCost = 3000000u, gasPriceFixedCost = 3000000u,
legacyFeesMultiplier = 1.2, legacyFeesMultiplier = 1.2,
margin = 4.0, margin = 4.0,
variableCostUpperBound = 10_000_000_001u, variableCostUpperBound = 10_000_000_001u,
variableCostLowerBound = 90_000_001u variableCostLowerBound = 90_000_001u,
), ),
jsonRpcPricingPropagation = JsonRpcPricingPropagationTomlDto( jsonRpcPricingPropagation = JsonRpcPricingPropagationTomlDto(
gethGasPriceUpdateRecipients = listOf( gethGasPriceUpdateRecipients = listOf(
URI("http://traces-node:8545/").toURL(), URI("http://traces-node:8545/").toURL(),
URI("http://l2-node:8545/").toURL() URI("http://l2-node:8545/").toURL(),
), ),
besuGasPriceUpdateRecipients = listOf( besuGasPriceUpdateRecipients = listOf(
URI("http://sequencer:8545/").toURL() URI("http://sequencer:8545/").toURL(),
) ),
), ),
extraDataPricingPropagation = ExtraDataPricingPropagationTomlDto( extraDataPricingPropagation = ExtraDataPricingPropagationTomlDto(
extraDataUpdateRecipient = URI("http://sequencer:8545/").toURL() extraDataUpdateRecipient = URI("http://sequencer:8545/").toURL(),
) ),
) ),
) )
} }
@@ -187,7 +187,7 @@ class L2NetworkGasPricingConfigTest {
maxRetries = 3, maxRetries = 3,
timeout = 6.seconds.toJavaDuration(), timeout = 6.seconds.toJavaDuration(),
backoffDelay = 1.seconds.toJavaDuration(), backoffDelay = 1.seconds.toJavaDuration(),
failuresWarningThreshold = 2 failuresWarningThreshold = 2,
), ),
priceUpdateInterval = Duration.parse("PT12S"), priceUpdateInterval = Duration.parse("PT12S"),
@@ -201,28 +201,28 @@ class L2NetworkGasPricingConfigTest {
type = LegacyGasPricingTomlDto.Type.SampleTransaction, type = LegacyGasPricingTomlDto.Type.SampleTransaction,
gasPriceUpperBound = 10_000_000_000u, gasPriceUpperBound = 10_000_000_000u,
gasPriceLowerBound = 90_000_000u, gasPriceLowerBound = 90_000_000u,
naiveGasPricing = null naiveGasPricing = null,
), ),
variableCostPricing = VariableCostPricingTomlDto( variableCostPricing = VariableCostPricingTomlDto(
gasPriceFixedCost = 3000000u, gasPriceFixedCost = 3000000u,
legacyFeesMultiplier = 1.2, legacyFeesMultiplier = 1.2,
margin = 4.0, margin = 4.0,
variableCostUpperBound = 10_000_000_001u, variableCostUpperBound = 10_000_000_001u,
variableCostLowerBound = 90_000_001u variableCostLowerBound = 90_000_001u,
), ),
jsonRpcPricingPropagation = JsonRpcPricingPropagationTomlDto( jsonRpcPricingPropagation = JsonRpcPricingPropagationTomlDto(
gethGasPriceUpdateRecipients = listOf( gethGasPriceUpdateRecipients = listOf(
URI("http://traces-node:8545/").toURL(), URI("http://traces-node:8545/").toURL(),
URI("http://l2-node:8545/").toURL() URI("http://l2-node:8545/").toURL(),
), ),
besuGasPriceUpdateRecipients = listOf( besuGasPriceUpdateRecipients = listOf(
URI("http://sequencer:8545/").toURL() URI("http://sequencer:8545/").toURL(),
) ),
), ),
extraDataPricingPropagation = ExtraDataPricingPropagationTomlDto( extraDataPricingPropagation = ExtraDataPricingPropagationTomlDto(
extraDataUpdateRecipient = URI("http://sequencer:8545/").toURL() extraDataUpdateRecipient = URI("http://sequencer:8545/").toURL(),
) ),
) ),
) )
} }
@@ -233,14 +233,14 @@ class L2NetworkGasPricingConfigTest {
maxRetries = 3u, maxRetries = 3u,
timeout = 6.seconds, timeout = 6.seconds,
backoffDelay = 1.seconds, backoffDelay = 1.seconds,
failuresWarningThreshold = 2u failuresWarningThreshold = 2u,
) )
assertThat(config).isEqualTo( assertThat(config).isEqualTo(
L2NetworkGasPricingService.Config( L2NetworkGasPricingService.Config(
feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config( feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config(
feeHistoryBlockCount = 50U, feeHistoryBlockCount = 50U,
feeHistoryRewardPercentile = 15.0 feeHistoryRewardPercentile = 15.0,
), ),
legacy = L2NetworkGasPricingService.LegacyGasPricingCalculatorConfig( legacy = L2NetworkGasPricingService.LegacyGasPricingCalculatorConfig(
naiveGasPricingCalculatorConfig = GasUsageRatioWeightedAverageFeesCalculator.Config( naiveGasPricingCalculatorConfig = GasUsageRatioWeightedAverageFeesCalculator.Config(
@@ -248,24 +248,24 @@ class L2NetworkGasPricingConfigTest {
priorityFeeCoefficient = 1.0, priorityFeeCoefficient = 1.0,
baseFeeBlobCoefficient = 0.1, baseFeeBlobCoefficient = 0.1,
blobSubmissionExpectedExecutionGas = 213_000, blobSubmissionExpectedExecutionGas = 213_000,
expectedBlobGas = 131072 expectedBlobGas = 131072,
), ),
legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config( legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config(
10_000_000_000.0, 10_000_000_000.0,
90_000_000.0, 90_000_000.0,
0.0 0.0,
), ),
transactionCostCalculatorConfig = null transactionCostCalculatorConfig = null,
), ),
jsonRpcGasPriceUpdaterConfig = GasPriceUpdaterImpl.Config( jsonRpcGasPriceUpdaterConfig = GasPriceUpdaterImpl.Config(
gethEndpoints = listOf( gethEndpoints = listOf(
URI("http://traces-node:8545/").toURL(), URI("http://traces-node:8545/").toURL(),
URI("http://l2-node:8545/").toURL() URI("http://l2-node:8545/").toURL(),
), ),
besuEndPoints = listOf( besuEndPoints = listOf(
URI("http://sequencer:8545/").toURL() URI("http://sequencer:8545/").toURL(),
), ),
retryConfig = l2NetworkGasPricingRequestretryConfig retryConfig = l2NetworkGasPricingRequestretryConfig,
), ),
jsonRpcPriceUpdateInterval = 12.seconds, jsonRpcPriceUpdateInterval = 12.seconds,
extraDataPricingPropagationEnabled = true, extraDataPricingPropagationEnabled = true,
@@ -274,22 +274,22 @@ class L2NetworkGasPricingConfigTest {
blobSubmissionExpectedExecutionGas = 213_000u, blobSubmissionExpectedExecutionGas = 213_000u,
bytesPerDataSubmission = 131072u, bytesPerDataSubmission = 131072u,
expectedBlobGas = 131072u, expectedBlobGas = 131072u,
margin = 4.0 margin = 4.0,
), ),
variableFeesCalculatorBounds = BoundableFeeCalculator.Config( variableFeesCalculatorBounds = BoundableFeeCalculator.Config(
feeUpperBound = 10_000_000_001.0, feeUpperBound = 10_000_000_001.0,
feeLowerBound = 90_000_001.0, feeLowerBound = 90_000_001.0,
feeMargin = 0.0 feeMargin = 0.0,
), ),
extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config( extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config(
fixedCostInKWei = 3000u, fixedCostInKWei = 3000u,
ethGasPriceMultiplier = 1.2 ethGasPriceMultiplier = 1.2,
), ),
extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config( extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config(
sequencerEndpoint = URI(/* str = */ "http://sequencer:8545/").toURL(), sequencerEndpoint = URI("http://sequencer:8545/").toURL(),
retryConfig = l2NetworkGasPricingRequestretryConfig retryConfig = l2NetworkGasPricingRequestretryConfig,
) ),
) ),
) )
} }
@@ -300,38 +300,38 @@ class L2NetworkGasPricingConfigTest {
maxRetries = 3u, maxRetries = 3u,
timeout = 6.seconds, timeout = 6.seconds,
backoffDelay = 1.seconds, backoffDelay = 1.seconds,
failuresWarningThreshold = 2u failuresWarningThreshold = 2u,
) )
assertThat(config).isEqualTo( assertThat(config).isEqualTo(
L2NetworkGasPricingService.Config( L2NetworkGasPricingService.Config(
feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config( feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config(
feeHistoryBlockCount = 50U, feeHistoryBlockCount = 50U,
feeHistoryRewardPercentile = 15.0 feeHistoryRewardPercentile = 15.0,
), ),
legacy = L2NetworkGasPricingService.LegacyGasPricingCalculatorConfig( legacy = L2NetworkGasPricingService.LegacyGasPricingCalculatorConfig(
naiveGasPricingCalculatorConfig = null, naiveGasPricingCalculatorConfig = null,
legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config( legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config(
10_000_000_000.0, 10_000_000_000.0,
90_000_000.0, 90_000_000.0,
0.0 0.0,
), ),
transactionCostCalculatorConfig = TransactionCostCalculator.Config( transactionCostCalculatorConfig = TransactionCostCalculator.Config(
sampleTransactionCostMultiplier = 1.0, sampleTransactionCostMultiplier = 1.0,
fixedCostWei = 3000000u, fixedCostWei = 3000000u,
compressedTxSize = 125, compressedTxSize = 125,
expectedGas = 21000 expectedGas = 21000,
) ),
), ),
jsonRpcGasPriceUpdaterConfig = GasPriceUpdaterImpl.Config( jsonRpcGasPriceUpdaterConfig = GasPriceUpdaterImpl.Config(
gethEndpoints = listOf( gethEndpoints = listOf(
URI("http://traces-node:8545/").toURL(), URI("http://traces-node:8545/").toURL(),
URI("http://l2-node:8545/").toURL() URI("http://l2-node:8545/").toURL(),
), ),
besuEndPoints = listOf( besuEndPoints = listOf(
URI("http://sequencer:8545/").toURL() URI("http://sequencer:8545/").toURL(),
), ),
retryConfig = l2NetworkGasPricingRequestretryConfig retryConfig = l2NetworkGasPricingRequestretryConfig,
), ),
jsonRpcPriceUpdateInterval = 12.seconds, jsonRpcPriceUpdateInterval = 12.seconds,
extraDataPricingPropagationEnabled = true, extraDataPricingPropagationEnabled = true,
@@ -340,22 +340,22 @@ class L2NetworkGasPricingConfigTest {
blobSubmissionExpectedExecutionGas = 213_000u, blobSubmissionExpectedExecutionGas = 213_000u,
bytesPerDataSubmission = 131072u, bytesPerDataSubmission = 131072u,
expectedBlobGas = 131072u, expectedBlobGas = 131072u,
margin = 4.0 margin = 4.0,
), ),
variableFeesCalculatorBounds = BoundableFeeCalculator.Config( variableFeesCalculatorBounds = BoundableFeeCalculator.Config(
feeUpperBound = 10_000_000_001.0, feeUpperBound = 10_000_000_001.0,
feeLowerBound = 90_000_001.0, feeLowerBound = 90_000_001.0,
feeMargin = 0.0 feeMargin = 0.0,
), ),
extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config( extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config(
fixedCostInKWei = 3000u, fixedCostInKWei = 3000u,
ethGasPriceMultiplier = 1.2 ethGasPriceMultiplier = 1.2,
), ),
extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config( extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config(
sequencerEndpoint = URI(/* str = */ "http://sequencer:8545/").toURL(), sequencerEndpoint = URI("http://sequencer:8545/").toURL(),
retryConfig = l2NetworkGasPricingRequestretryConfig retryConfig = l2NetworkGasPricingRequestretryConfig,
) ),
) ),
) )
} }
@@ -400,28 +400,28 @@ class L2NetworkGasPricingConfigTest {
maxRetries = 3u, maxRetries = 3u,
timeout = 6.seconds, timeout = 6.seconds,
backoffDelay = 1.seconds, backoffDelay = 1.seconds,
failuresWarningThreshold = 2u failuresWarningThreshold = 2u,
) )
assertThat(config).isEqualTo( assertThat(config).isEqualTo(
L2NetworkGasPricingService.Config( L2NetworkGasPricingService.Config(
feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config( feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config(
feeHistoryBlockCount = 50U, feeHistoryBlockCount = 50U,
feeHistoryRewardPercentile = 15.0 feeHistoryRewardPercentile = 15.0,
), ),
legacy = L2NetworkGasPricingService.LegacyGasPricingCalculatorConfig( legacy = L2NetworkGasPricingService.LegacyGasPricingCalculatorConfig(
naiveGasPricingCalculatorConfig = null, naiveGasPricingCalculatorConfig = null,
legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config( legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config(
10_000_000_000.0, 10_000_000_000.0,
90_000_000.0, 90_000_000.0,
0.0 0.0,
), ),
transactionCostCalculatorConfig = TransactionCostCalculator.Config( transactionCostCalculatorConfig = TransactionCostCalculator.Config(
sampleTransactionCostMultiplier = 1.0, sampleTransactionCostMultiplier = 1.0,
fixedCostWei = 3000000u, fixedCostWei = 3000000u,
compressedTxSize = 125, compressedTxSize = 125,
expectedGas = 21000 expectedGas = 21000,
) ),
), ),
jsonRpcGasPriceUpdaterConfig = null, jsonRpcGasPriceUpdaterConfig = null,
jsonRpcPriceUpdateInterval = 12.seconds, jsonRpcPriceUpdateInterval = 12.seconds,
@@ -431,22 +431,22 @@ class L2NetworkGasPricingConfigTest {
blobSubmissionExpectedExecutionGas = 213_000u, blobSubmissionExpectedExecutionGas = 213_000u,
bytesPerDataSubmission = 131072u, bytesPerDataSubmission = 131072u,
expectedBlobGas = 131072u, expectedBlobGas = 131072u,
margin = 4.0 margin = 4.0,
), ),
variableFeesCalculatorBounds = BoundableFeeCalculator.Config( variableFeesCalculatorBounds = BoundableFeeCalculator.Config(
feeUpperBound = 10_000_000_001.0, feeUpperBound = 10_000_000_001.0,
feeLowerBound = 90_000_001.0, feeLowerBound = 90_000_001.0,
feeMargin = 0.0 feeMargin = 0.0,
), ),
extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config( extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config(
fixedCostInKWei = 3000u, fixedCostInKWei = 3000u,
ethGasPriceMultiplier = 1.2 ethGasPriceMultiplier = 1.2,
), ),
extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config( extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config(
sequencerEndpoint = URI(/* str = */ "http://sequencer:8545/").toURL(), sequencerEndpoint = URI("http://sequencer:8545/").toURL(),
retryConfig = l2NetworkGasPricingRequestretryConfig retryConfig = l2NetworkGasPricingRequestretryConfig,
) ),
) ),
) )
} }
@@ -496,28 +496,28 @@ class L2NetworkGasPricingConfigTest {
maxRetries = 3u, maxRetries = 3u,
timeout = 6.seconds, timeout = 6.seconds,
backoffDelay = 1.seconds, backoffDelay = 1.seconds,
failuresWarningThreshold = 2u failuresWarningThreshold = 2u,
) )
assertThat(config).isEqualTo( assertThat(config).isEqualTo(
L2NetworkGasPricingService.Config( L2NetworkGasPricingService.Config(
feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config( feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config(
feeHistoryBlockCount = 50U, feeHistoryBlockCount = 50U,
feeHistoryRewardPercentile = 15.0 feeHistoryRewardPercentile = 15.0,
), ),
legacy = L2NetworkGasPricingService.LegacyGasPricingCalculatorConfig( legacy = L2NetworkGasPricingService.LegacyGasPricingCalculatorConfig(
naiveGasPricingCalculatorConfig = null, naiveGasPricingCalculatorConfig = null,
legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config( legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config(
10_000_000_000.0, 10_000_000_000.0,
90_000_000.0, 90_000_000.0,
0.0 0.0,
), ),
transactionCostCalculatorConfig = TransactionCostCalculator.Config( transactionCostCalculatorConfig = TransactionCostCalculator.Config(
sampleTransactionCostMultiplier = 1.0, sampleTransactionCostMultiplier = 1.0,
fixedCostWei = 3000000u, fixedCostWei = 3000000u,
compressedTxSize = 125, compressedTxSize = 125,
expectedGas = 21000 expectedGas = 21000,
) ),
), ),
jsonRpcGasPriceUpdaterConfig = null, jsonRpcGasPriceUpdaterConfig = null,
jsonRpcPriceUpdateInterval = 12.seconds, jsonRpcPriceUpdateInterval = 12.seconds,
@@ -527,22 +527,22 @@ class L2NetworkGasPricingConfigTest {
blobSubmissionExpectedExecutionGas = 213_000u, blobSubmissionExpectedExecutionGas = 213_000u,
bytesPerDataSubmission = 131072u, bytesPerDataSubmission = 131072u,
expectedBlobGas = 131072u, expectedBlobGas = 131072u,
margin = 4.0 margin = 4.0,
), ),
variableFeesCalculatorBounds = BoundableFeeCalculator.Config( variableFeesCalculatorBounds = BoundableFeeCalculator.Config(
feeUpperBound = 10_000_000_001.0, feeUpperBound = 10_000_000_001.0,
feeLowerBound = 90_000_001.0, feeLowerBound = 90_000_001.0,
feeMargin = 0.0 feeMargin = 0.0,
), ),
extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config( extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config(
fixedCostInKWei = 3000u, fixedCostInKWei = 3000u,
ethGasPriceMultiplier = 1.2 ethGasPriceMultiplier = 1.2,
), ),
extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config( extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config(
sequencerEndpoint = URI(/* str = */ "http://sequencer:8545/").toURL(), sequencerEndpoint = URI("http://sequencer:8545/").toURL(),
retryConfig = l2NetworkGasPricingRequestretryConfig retryConfig = l2NetworkGasPricingRequestretryConfig,
) ),
) ),
) )
} }
} }

View File

@@ -14,7 +14,7 @@ class MessageAnchoringConfigTest {
private val l1DefaultEndpoint = URI("http://l1-default-rpc-endpoint:8545").toURL() private val l1DefaultEndpoint = URI("http://l1-default-rpc-endpoint:8545").toURL()
private val l2DefaultEndpoint = URI("http://l2-default-rpc-endpoint:8545").toURL() private val l2DefaultEndpoint = URI("http://l2-default-rpc-endpoint:8545").toURL()
data class Config( data class Config(
val messageAnchoring: MessageAnchoringConfigTomlDto = MessageAnchoringConfigTomlDto() val messageAnchoring: MessageAnchoringConfigTomlDto = MessageAnchoringConfigTomlDto(),
) )
private fun parseConfig(toml: String): MessageAnchoringConfig { private fun parseConfig(toml: String): MessageAnchoringConfig {
@@ -27,7 +27,7 @@ class MessageAnchoringConfigTest {
.let { .let {
it.messageAnchoring.reified( it.messageAnchoring.reified(
l1DefaultEndpoint = l1DefaultEndpoint, l1DefaultEndpoint = l1DefaultEndpoint,
l2DefaultEndpoint = l2DefaultEndpoint l2DefaultEndpoint = l2DefaultEndpoint,
) )
} }
} }
@@ -74,13 +74,13 @@ class MessageAnchoringConfigTest {
maxRetries = 10u, maxRetries = 10u,
timeout = 100.seconds, timeout = 100.seconds,
backoffDelay = 11.seconds, backoffDelay = 11.seconds,
failuresWarningThreshold = 1u failuresWarningThreshold = 1u,
), ),
l2RequestRetryConfig = RetryConfig( l2RequestRetryConfig = RetryConfig(
maxRetries = 20u, maxRetries = 20u,
timeout = 200.seconds, timeout = 200.seconds,
backoffDelay = 21.seconds, backoffDelay = 21.seconds,
failuresWarningThreshold = 2u failuresWarningThreshold = 2u,
), ),
l1EventPollingInterval = 30.seconds, l1EventPollingInterval = 30.seconds,
l1EventPollingTimeout = 6.seconds, l1EventPollingTimeout = 6.seconds,
@@ -88,8 +88,8 @@ class MessageAnchoringConfigTest {
l1EventSearchBlockChunk = 123u, l1EventSearchBlockChunk = 123u,
anchoringTickInterval = 3.seconds, anchoringTickInterval = 3.seconds,
messageQueueCapacity = 321u, messageQueueCapacity = 321u,
maxMessagesToAnchorPerL2Transaction = 54u maxMessagesToAnchorPerL2Transaction = 54u,
) ),
) )
} }
@@ -111,13 +111,13 @@ class MessageAnchoringConfigTest {
maxRetries = null, maxRetries = null,
timeout = null, timeout = null,
backoffDelay = 1.seconds, backoffDelay = 1.seconds,
failuresWarningThreshold = 3u failuresWarningThreshold = 3u,
), ),
l2RequestRetryConfig = RetryConfig( l2RequestRetryConfig = RetryConfig(
maxRetries = null, maxRetries = null,
timeout = null, timeout = null,
backoffDelay = 1.seconds, backoffDelay = 1.seconds,
failuresWarningThreshold = 3u failuresWarningThreshold = 3u,
), ),
l1EventPollingInterval = 12.seconds, l1EventPollingInterval = 12.seconds,
l1EventPollingTimeout = 6.seconds, l1EventPollingTimeout = 6.seconds,
@@ -125,8 +125,8 @@ class MessageAnchoringConfigTest {
l1EventSearchBlockChunk = 1000u, l1EventSearchBlockChunk = 1000u,
anchoringTickInterval = 2.seconds, anchoringTickInterval = 2.seconds,
messageQueueCapacity = 10_000u, messageQueueCapacity = 10_000u,
maxMessagesToAnchorPerL2Transaction = 100u maxMessagesToAnchorPerL2Transaction = 100u,
) ),
) )
} }
} }

View File

@@ -13,7 +13,7 @@ import kotlin.time.Duration.Companion.seconds
class ProverConfigTest { class ProverConfigTest {
data class Config( data class Config(
val prover: ProverConfigTomlDto val prover: ProverConfigTomlDto,
) )
private fun parseConfig(toml: String): ProversConfig { private fun parseConfig(toml: String): ProversConfig {
@@ -62,8 +62,8 @@ class ProverConfigTest {
inprogressRequestWritingSuffix = ".OVERRIDE_inprogress_coordinator_writing", inprogressRequestWritingSuffix = ".OVERRIDE_inprogress_coordinator_writing",
inprogressProvingSuffixPattern = "OVERRIDE_\\.inprogress\\.prover.*", inprogressProvingSuffixPattern = "OVERRIDE_\\.inprogress\\.prover.*",
pollingInterval = 10.seconds, pollingInterval = 10.seconds,
pollingTimeout = 10.minutes pollingTimeout = 10.minutes,
) ),
) )
assertThat(config.blobCompression).isEqualTo( assertThat(config.blobCompression).isEqualTo(
FileBasedProverConfig( FileBasedProverConfig(
@@ -72,8 +72,8 @@ class ProverConfigTest {
inprogressRequestWritingSuffix = ".inprogress_coordinator_writing", inprogressRequestWritingSuffix = ".inprogress_coordinator_writing",
inprogressProvingSuffixPattern = "\\.inprogress\\.prover.*", inprogressProvingSuffixPattern = "\\.inprogress\\.prover.*",
pollingInterval = 20.seconds, pollingInterval = 20.seconds,
pollingTimeout = 20.minutes pollingTimeout = 20.minutes,
) ),
) )
assertThat(config.proofAggregation).isEqualTo( assertThat(config.proofAggregation).isEqualTo(
FileBasedProverConfig( FileBasedProverConfig(
@@ -82,8 +82,8 @@ class ProverConfigTest {
inprogressRequestWritingSuffix = ".inprogress_coordinator_writing", inprogressRequestWritingSuffix = ".inprogress_coordinator_writing",
inprogressProvingSuffixPattern = "\\.inprogress\\.prover.*", inprogressProvingSuffixPattern = "\\.inprogress\\.prover.*",
pollingInterval = 10.seconds, pollingInterval = 10.seconds,
pollingTimeout = 10.minutes pollingTimeout = 10.minutes,
) ),
) )
} }
@@ -122,8 +122,8 @@ class ProverConfigTest {
inprogressRequestWritingSuffix = ".NEW_OVERRIDE_2_inprogress_coordinator_writing", inprogressRequestWritingSuffix = ".NEW_OVERRIDE_2_inprogress_coordinator_writing",
inprogressProvingSuffixPattern = "NEW_OVERRIDE_2\\.inprogress\\.prover.*", inprogressProvingSuffixPattern = "NEW_OVERRIDE_2\\.inprogress\\.prover.*",
pollingInterval = 10.seconds, pollingInterval = 10.seconds,
pollingTimeout = 5.minutes pollingTimeout = 5.minutes,
) ),
) )
assertThat(config.proverB!!.blobCompression).isEqualTo( assertThat(config.proverB!!.blobCompression).isEqualTo(
FileBasedProverConfig( FileBasedProverConfig(
@@ -132,8 +132,8 @@ class ProverConfigTest {
inprogressRequestWritingSuffix = ".NEW_OVERRIDE_inprogress_coordinator_writing", inprogressRequestWritingSuffix = ".NEW_OVERRIDE_inprogress_coordinator_writing",
inprogressProvingSuffixPattern = "\\.inprogress\\.prover.*", inprogressProvingSuffixPattern = "\\.inprogress\\.prover.*",
pollingInterval = 12.seconds, pollingInterval = 12.seconds,
pollingTimeout = 12.minutes pollingTimeout = 12.minutes,
) ),
) )
assertThat(config.proverB!!.proofAggregation).isEqualTo( assertThat(config.proverB!!.proofAggregation).isEqualTo(
FileBasedProverConfig( FileBasedProverConfig(
@@ -142,8 +142,8 @@ class ProverConfigTest {
inprogressRequestWritingSuffix = ".NEW_OVERRIDE_inprogress_coordinator_writing", inprogressRequestWritingSuffix = ".NEW_OVERRIDE_inprogress_coordinator_writing",
inprogressProvingSuffixPattern = "\\.inprogress\\.prover.*", inprogressProvingSuffixPattern = "\\.inprogress\\.prover.*",
pollingInterval = 10.seconds, pollingInterval = 10.seconds,
pollingTimeout = 5.minutes pollingTimeout = 5.minutes,
) ),
) )
} }
} }

View File

@@ -44,7 +44,7 @@ class BlockCreationMonitorTest {
pollingInterval = 100.milliseconds, pollingInterval = 100.milliseconds,
blocksToFinalization = 2L, blocksToFinalization = 2L,
blocksFetchLimit = 500, blocksFetchLimit = 500,
lastL2BlockNumberToProcessInclusive = null lastL2BlockNumberToProcessInclusive = null,
) )
private lateinit var vertx: Vertx private lateinit var vertx: Vertx
private lateinit var lastProvenBlockNumberProvider: LastProvenBlockNumberProviderDouble private lateinit var lastProvenBlockNumberProvider: LastProvenBlockNumberProviderDouble
@@ -62,7 +62,7 @@ class BlockCreationMonitorTest {
} }
private class LastProvenBlockNumberProviderDouble( private class LastProvenBlockNumberProviderDouble(
initialValue: ULong initialValue: ULong,
) : LastProvenBlockNumberProviderAsync { ) : LastProvenBlockNumberProviderAsync {
var lastProvenBlock: AtomicLong = AtomicLong(initialValue.toLong()) var lastProvenBlock: AtomicLong = AtomicLong(initialValue.toLong())
override fun getLastProvenBlockNumber(): SafeFuture<Long> { override fun getLastProvenBlockNumber(): SafeFuture<Long> {
@@ -73,7 +73,7 @@ class BlockCreationMonitorTest {
fun createBlockCreationMonitor( fun createBlockCreationMonitor(
startingBlockNumberExclusive: Long = 99, startingBlockNumberExclusive: Long = 99,
blockCreationListener: BlockCreationListener = this.blockCreationListener, blockCreationListener: BlockCreationListener = this.blockCreationListener,
config: BlockCreationMonitor.Config = this.config config: BlockCreationMonitor.Config = this.config,
): BlockCreationMonitor { ): BlockCreationMonitor {
return BlockCreationMonitor( return BlockCreationMonitor(
this.vertx, this.vertx,
@@ -81,7 +81,7 @@ class BlockCreationMonitorTest {
startingBlockNumberExclusive = startingBlockNumberExclusive, startingBlockNumberExclusive = startingBlockNumberExclusive,
blockCreationListener, blockCreationListener,
lastProvenBlockNumberProvider, lastProvenBlockNumberProvider,
config config,
) )
} }
@@ -94,14 +94,14 @@ class BlockCreationMonitorTest {
fakeL2RpcNode = TestingJsonRpcServer( fakeL2RpcNode = TestingJsonRpcServer(
vertx = vertx, vertx = vertx,
recordRequestsResponses = true, recordRequestsResponses = true,
responseObjectMapper = ethApiObjectMapper responseObjectMapper = ethApiObjectMapper,
) )
blockCreationListener = BlockCreationListenerDouble() blockCreationListener = BlockCreationListenerDouble()
web3jClient = ExtendedWeb3JImpl( web3jClient = ExtendedWeb3JImpl(
createWeb3jHttpClient( createWeb3jHttpClient(
rpcUrl = "http://localhost:${fakeL2RpcNode.boundPort}", rpcUrl = "http://localhost:${fakeL2RpcNode.boundPort}",
log = LogManager.getLogger("test.client.l2.web3j") log = LogManager.getLogger("test.client.l2.web3j"),
) ),
) )
lastProvenBlockNumberProvider = LastProvenBlockNumberProviderDouble(99u) lastProvenBlockNumberProvider = LastProvenBlockNumberProviderDouble(99u)
} }
@@ -116,7 +116,7 @@ class BlockCreationMonitorTest {
startBlockNumber: ULong, startBlockNumber: ULong,
numberOfBlocks: Int, numberOfBlocks: Int,
startBlockHash: ByteArray = ByteArrayExt.random32(), startBlockHash: ByteArray = ByteArrayExt.random32(),
startBlockParentHash: ByteArray = ByteArrayExt.random32() startBlockParentHash: ByteArray = ByteArrayExt.random32(),
): List<Block> { ): List<Block> {
var blockHash = startBlockHash var blockHash = startBlockHash
var parentHash = startBlockParentHash var parentHash = startBlockParentHash
@@ -124,7 +124,7 @@ class BlockCreationMonitorTest {
createBlock( createBlock(
number = startBlockNumber + i.toULong(), number = startBlockNumber + i.toULong(),
hash = blockHash, hash = blockHash,
parentHash = parentHash parentHash = parentHash,
).also { ).also {
blockHash = ByteArrayExt.random32() blockHash = ByteArrayExt.random32()
parentHash = it.hash parentHash = it.hash
@@ -147,7 +147,7 @@ class BlockCreationMonitorTest {
fun `should stop fetching blocks after lastBlockNumberInclusiveToProcess`() { fun `should stop fetching blocks after lastBlockNumberInclusiveToProcess`() {
monitor = createBlockCreationMonitor( monitor = createBlockCreationMonitor(
startingBlockNumberExclusive = 99, startingBlockNumberExclusive = 99,
config = config.copy(lastL2BlockNumberToProcessInclusive = 103u) config = config.copy(lastL2BlockNumberToProcessInclusive = 103u),
) )
setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 20)) setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 20))
@@ -170,7 +170,7 @@ class BlockCreationMonitorTest {
fun `should notify lister only after block is considered final on L2`() { fun `should notify lister only after block is considered final on L2`() {
monitor = createBlockCreationMonitor( monitor = createBlockCreationMonitor(
startingBlockNumberExclusive = 99, startingBlockNumberExclusive = 99,
config = config.copy(blocksToFinalization = 2, blocksFetchLimit = 500) config = config.copy(blocksToFinalization = 2, blocksFetchLimit = 500),
) )
setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 200)) setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 200))
@@ -217,7 +217,7 @@ class BlockCreationMonitorTest {
monitor = createBlockCreationMonitor( monitor = createBlockCreationMonitor(
startingBlockNumberExclusive = 99, startingBlockNumberExclusive = 99,
blockCreationListener = fakeBuggyLister, blockCreationListener = fakeBuggyLister,
config = config.copy(blocksToFinalization = 2, lastL2BlockNumberToProcessInclusive = 112u) config = config.copy(blocksToFinalization = 2, lastL2BlockNumberToProcessInclusive = 112u),
) )
setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 20)) setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 20))
@@ -232,14 +232,14 @@ class BlockCreationMonitorTest {
// assert it got block only once and in order // assert it got block only once and in order
assertThat(blockCreationListener.blocksReceived.map { it.number }).containsExactly( assertThat(blockCreationListener.blocksReceived.map { it.number }).containsExactly(
100UL, 101UL, 102UL, 103UL, 104UL, 105UL, 106UL, 107UL, 108UL, 109UL, 110UL 100UL, 101UL, 102UL, 103UL, 104UL, 105UL, 106UL, 107UL, 108UL, 109UL, 110UL,
) )
} }
@Test @Test
fun `should be resilient to connection failures`() { fun `should be resilient to connection failures`() {
monitor = createBlockCreationMonitor( monitor = createBlockCreationMonitor(
startingBlockNumberExclusive = 99 startingBlockNumberExclusive = 99,
) )
setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 200)) setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 200))
@@ -268,7 +268,7 @@ class BlockCreationMonitorTest {
@Test @Test
fun `should stop when reorg is detected above blocksToFinalization limit - manual intervention necessary`() { fun `should stop when reorg is detected above blocksToFinalization limit - manual intervention necessary`() {
monitor = createBlockCreationMonitor( monitor = createBlockCreationMonitor(
startingBlockNumberExclusive = 99 startingBlockNumberExclusive = 99,
) )
// simulate reorg by changing parent hash of block 105 // simulate reorg by changing parent hash of block 105
@@ -300,7 +300,7 @@ class BlockCreationMonitorTest {
fun `should poll in order when response takes longer that polling interval`() { fun `should poll in order when response takes longer that polling interval`() {
monitor = createBlockCreationMonitor( monitor = createBlockCreationMonitor(
startingBlockNumberExclusive = 99, startingBlockNumberExclusive = 99,
config = config.copy(pollingInterval = 100.milliseconds) config = config.copy(pollingInterval = 100.milliseconds),
) )
val blocks = createBlocks(startBlockNumber = 99u, numberOfBlocks = 20) val blocks = createBlocks(startBlockNumber = 99u, numberOfBlocks = 20)
@@ -318,7 +318,7 @@ class BlockCreationMonitorTest {
102UL, 102UL,
103UL, 103UL,
104UL, 104UL,
105UL 105UL,
) )
} }
} }
@@ -326,7 +326,7 @@ class BlockCreationMonitorTest {
@Test @Test
fun `start allow 2nd call when already started`() { fun `start allow 2nd call when already started`() {
monitor = createBlockCreationMonitor( monitor = createBlockCreationMonitor(
startingBlockNumberExclusive = 99 startingBlockNumberExclusive = 99,
) )
setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 5)) setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 5))
monitor.start().get() monitor.start().get()
@@ -337,7 +337,7 @@ class BlockCreationMonitorTest {
fun `should stop fetching blocks when gap is greater than fetch limit and resume upon catchup`() { fun `should stop fetching blocks when gap is greater than fetch limit and resume upon catchup`() {
monitor = createBlockCreationMonitor( monitor = createBlockCreationMonitor(
startingBlockNumberExclusive = 99, startingBlockNumberExclusive = 99,
config = config.copy(blocksToFinalization = 0, blocksFetchLimit = 5) config = config.copy(blocksToFinalization = 0, blocksFetchLimit = 5),
) )
setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 30)) setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 30))

View File

@@ -27,23 +27,23 @@ class ConsecutiveProvenBlobsProviderWithLastEndBlockNumberTrackerTest {
endBlockNumber = 2UL, endBlockNumber = 2UL,
startBlockTimestamp = Instant.DISTANT_PAST, startBlockTimestamp = Instant.DISTANT_PAST,
endBlockTimestamp = Instant.DISTANT_PAST, endBlockTimestamp = Instant.DISTANT_PAST,
expectedShnarf = Random.nextBytes(32) expectedShnarf = Random.nextBytes(32),
) )
val baseBlobAndBatchCounters = BlobAndBatchCounters( val baseBlobAndBatchCounters = BlobAndBatchCounters(
blobCounters = baseBlobCounters, blobCounters = baseBlobCounters,
executionProofs = BlockIntervals(1UL, listOf(2UL, 3UL)) executionProofs = BlockIntervals(1UL, listOf(2UL, 3UL)),
) )
val expectedEndBLockNumber = 10UL val expectedEndBLockNumber = 10UL
val lastBlobAndBatchCounters = baseBlobAndBatchCounters.copy( val lastBlobAndBatchCounters = baseBlobAndBatchCounters.copy(
blobCounters = baseBlobCounters.copy(startBlockNumber = 3UL, endBlockNumber = expectedEndBLockNumber) blobCounters = baseBlobCounters.copy(startBlockNumber = 3UL, endBlockNumber = expectedEndBLockNumber),
) )
whenever(repositoryMock.findConsecutiveProvenBlobs(any())).thenReturn( whenever(repositoryMock.findConsecutiveProvenBlobs(any())).thenReturn(
SafeFuture.completedFuture( SafeFuture.completedFuture(
listOf( listOf(
baseBlobAndBatchCounters, baseBlobAndBatchCounters,
lastBlobAndBatchCounters lastBlobAndBatchCounters,
) ),
) ),
) )
cache.findConsecutiveProvenBlobs(expectedEndBLockNumber.toLong()) cache.findConsecutiveProvenBlobs(expectedEndBLockNumber.toLong())

View File

@@ -22,12 +22,12 @@ class ForkChoiceUpdaterImplTest {
fun dispatchFinalizedBlockNotification_allClientsSuccess() { fun dispatchFinalizedBlockNotification_allClientsSuccess() {
val mockClient1 = mock<RollupForkChoiceUpdatedClient>() val mockClient1 = mock<RollupForkChoiceUpdatedClient>()
whenever( whenever(
mockClient1.rollupForkChoiceUpdated(any()) mockClient1.rollupForkChoiceUpdated(any()),
) )
.thenReturn(SafeFuture.completedFuture(Ok(RollupForkChoiceUpdatedResponse("success")))) .thenReturn(SafeFuture.completedFuture(Ok(RollupForkChoiceUpdatedResponse("success"))))
val mockClient2 = mock<RollupForkChoiceUpdatedClient>() val mockClient2 = mock<RollupForkChoiceUpdatedClient>()
whenever( whenever(
mockClient2.rollupForkChoiceUpdated(any()) mockClient2.rollupForkChoiceUpdated(any()),
) )
.thenReturn(SafeFuture.completedFuture(Ok(RollupForkChoiceUpdatedResponse("success")))) .thenReturn(SafeFuture.completedFuture(Ok(RollupForkChoiceUpdatedResponse("success"))))
@@ -43,12 +43,12 @@ class ForkChoiceUpdaterImplTest {
fun dispatchFinalizedBlockNotification_someClientsFail() { fun dispatchFinalizedBlockNotification_someClientsFail() {
val mockClient1 = mock<RollupForkChoiceUpdatedClient>() val mockClient1 = mock<RollupForkChoiceUpdatedClient>()
whenever( whenever(
mockClient1.rollupForkChoiceUpdated(any()) mockClient1.rollupForkChoiceUpdated(any()),
) )
.thenReturn(SafeFuture.completedFuture(Ok(RollupForkChoiceUpdatedResponse("success")))) .thenReturn(SafeFuture.completedFuture(Ok(RollupForkChoiceUpdatedResponse("success"))))
val mockClient2 = mock<RollupForkChoiceUpdatedClient>() val mockClient2 = mock<RollupForkChoiceUpdatedClient>()
whenever( whenever(
mockClient2.rollupForkChoiceUpdated(any()) mockClient2.rollupForkChoiceUpdated(any()),
) )
.thenReturn(SafeFuture.completedFuture(Err(ErrorResponse(RollupForkChoiceUpdatedError.UNKNOWN, "")))) .thenReturn(SafeFuture.completedFuture(Err(ErrorResponse(RollupForkChoiceUpdatedError.UNKNOWN, ""))))

View File

@@ -17,7 +17,7 @@ class SimpleCompositeSafeFutureHandlerTest {
handler2Calls.add("handler2:$value") handler2Calls.add("handler2:$value")
SafeFuture.failedFuture(RuntimeException("Handler 2 failed")) SafeFuture.failedFuture(RuntimeException("Handler 2 failed"))
}, },
{ value: Long -> SafeFuture.completedFuture(handler3Calls.add("handler3:$value")) } { value: Long -> SafeFuture.completedFuture(handler3Calls.add("handler3:$value")) },
) )
SimpleCompositeSafeFutureHandler(handlers).invoke(123) SimpleCompositeSafeFutureHandler(handlers).invoke(123)
@@ -34,8 +34,11 @@ class SimpleCompositeSafeFutureHandlerTest {
val handler3Calls = mutableListOf<String>() val handler3Calls = mutableListOf<String>()
val handlers = listOf( val handlers = listOf(
{ value: Long -> SafeFuture.completedFuture(handler1Calls.add("handler1:$value")) }, { value: Long -> SafeFuture.completedFuture(handler1Calls.add("handler1:$value")) },
{ value: Long -> handler2Calls.add("handler2:$value"); throw RuntimeException("Forced error") }, { value: Long ->
{ value: Long -> SafeFuture.completedFuture(handler3Calls.add("handler3:$value")) } handler2Calls.add("handler2:$value")
throw RuntimeException("Forced error")
},
{ value: Long -> SafeFuture.completedFuture(handler3Calls.add("handler3:$value")) },
) )
SimpleCompositeSafeFutureHandler(handlers).invoke(123) SimpleCompositeSafeFutureHandler(handlers).invoke(123)

View File

@@ -5,7 +5,7 @@ import net.consensys.zkevm.coordinator.clients.ProverClient
import tech.pegasys.teku.infrastructure.async.SafeFuture import tech.pegasys.teku.infrastructure.async.SafeFuture
class StartBlockNumberBasedSwitchPredicate<ProofRequest>( class StartBlockNumberBasedSwitchPredicate<ProofRequest>(
private val switchStartBlockNumberInclusive: ULong private val switchStartBlockNumberInclusive: ULong,
) where ProofRequest : BlockInterval { ) where ProofRequest : BlockInterval {
fun invoke(proofRequest: ProofRequest): Boolean = proofRequest.startBlockNumber >= switchStartBlockNumberInclusive fun invoke(proofRequest: ProofRequest): Boolean = proofRequest.startBlockNumber >= switchStartBlockNumberInclusive
} }
@@ -13,7 +13,7 @@ class StartBlockNumberBasedSwitchPredicate<ProofRequest>(
class ABProverClientRouter<ProofRequest, ProofResponse>( class ABProverClientRouter<ProofRequest, ProofResponse>(
private val proverA: ProverClient<ProofRequest, ProofResponse>, private val proverA: ProverClient<ProofRequest, ProofResponse>,
private val proverB: ProverClient<ProofRequest, ProofResponse>, private val proverB: ProverClient<ProofRequest, ProofResponse>,
private val switchToProverBPredicate: (ProofRequest) -> Boolean private val switchToProverBPredicate: (ProofRequest) -> Boolean,
) : ProverClient<ProofRequest, ProofResponse> { ) : ProverClient<ProofRequest, ProofResponse> {
override fun requestProof(proofRequest: ProofRequest): SafeFuture<ProofResponse> { override fun requestProof(proofRequest: ProofRequest): SafeFuture<ProofResponse> {

View File

@@ -6,13 +6,13 @@ import kotlin.time.Duration
data class ProversConfig( data class ProversConfig(
val proverA: ProverConfig, val proverA: ProverConfig,
val switchBlockNumberInclusive: ULong?, val switchBlockNumberInclusive: ULong?,
val proverB: ProverConfig? val proverB: ProverConfig?,
) )
data class ProverConfig( data class ProverConfig(
val execution: FileBasedProverConfig, val execution: FileBasedProverConfig,
val blobCompression: FileBasedProverConfig, val blobCompression: FileBasedProverConfig,
val proofAggregation: FileBasedProverConfig val proofAggregation: FileBasedProverConfig,
) )
data class FileBasedProverConfig( data class FileBasedProverConfig(
@@ -21,5 +21,5 @@ data class FileBasedProverConfig(
val inprogressProvingSuffixPattern: String, val inprogressProvingSuffixPattern: String,
val inprogressRequestWritingSuffix: String, val inprogressRequestWritingSuffix: String,
val pollingInterval: Duration, val pollingInterval: Duration,
val pollingTimeout: Duration val pollingTimeout: Duration,
) )

View File

@@ -28,13 +28,13 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture
class FileBasedBlobCompressionProverClientV2( class FileBasedBlobCompressionProverClientV2(
val config: FileBasedProverConfig, val config: FileBasedProverConfig,
val vertx: Vertx, val vertx: Vertx,
jsonObjectMapper: ObjectMapper = JsonSerialization.proofResponseMapperV1 jsonObjectMapper: ObjectMapper = JsonSerialization.proofResponseMapperV1,
) : ) :
GenericFileBasedProverClient< GenericFileBasedProverClient<
BlobCompressionProofRequest, BlobCompressionProofRequest,
BlobCompressionProof, BlobCompressionProof,
BlobCompressionProofJsonRequest, BlobCompressionProofJsonRequest,
BlobCompressionProofJsonResponse BlobCompressionProofJsonResponse,
>( >(
config = config, config = config,
vertx = vertx, vertx = vertx,
@@ -42,7 +42,7 @@ class FileBasedBlobCompressionProverClientV2(
fileReader = FileReader( fileReader = FileReader(
vertx, vertx,
jsonObjectMapper, jsonObjectMapper,
BlobCompressionProofJsonResponse::class.java BlobCompressionProofJsonResponse::class.java,
), ),
requestFileNameProvider = CompressionProofRequestFileNameProvider, requestFileNameProvider = CompressionProofRequestFileNameProvider,
responseFileNameProvider = CompressionProofResponseFileNameProvider, responseFileNameProvider = CompressionProofResponseFileNameProvider,
@@ -50,7 +50,7 @@ class FileBasedBlobCompressionProverClientV2(
requestMapper = FileBasedBlobCompressionProverClientV2::requestDtoMapper, requestMapper = FileBasedBlobCompressionProverClientV2::requestDtoMapper,
responseMapper = BlobCompressionProofJsonResponse::toDomainObject, responseMapper = BlobCompressionProofJsonResponse::toDomainObject,
proofTypeLabel = "blob", proofTypeLabel = "blob",
log = LogManager.getLogger(this::class.java) log = LogManager.getLogger(this::class.java),
), ),
BlobCompressionProverClientV2 { BlobCompressionProverClientV2 {
@@ -59,7 +59,7 @@ class FileBasedBlobCompressionProverClientV2(
return ProofIndex( return ProofIndex(
startBlockNumber = request.startBlockNumber, startBlockNumber = request.startBlockNumber,
endBlockNumber = request.endBlockNumber, endBlockNumber = request.endBlockNumber,
hash = request.expectedShnarfResult.expectedShnarf hash = request.expectedShnarfResult.expectedShnarf,
) )
} }

View File

@@ -26,7 +26,7 @@ data class BatchExecutionProofRequestDto(
val tracesEngineVersion: String, val tracesEngineVersion: String,
val type2StateManagerVersion: String?, val type2StateManagerVersion: String?,
val zkStateMerkleProof: ArrayNode, val zkStateMerkleProof: ArrayNode,
val blocksData: List<RlpBridgeLogsDto> val blocksData: List<RlpBridgeLogsDto>,
) )
data class RlpBridgeLogsDto(val rlp: String, val bridgeLogs: List<BridgeLogsDto>) data class RlpBridgeLogsDto(val rlp: String, val bridgeLogs: List<BridgeLogsDto>)
@@ -40,7 +40,7 @@ data class BridgeLogsDto(
val blockNumber: String, val blockNumber: String,
val address: String, val address: String,
val data: String, val data: String,
val topics: List<String> val topics: List<String>,
) { ) {
companion object { companion object {
fun fromDomainObject(ethLog: EthLog): BridgeLogsDto { fun fromDomainObject(ethLog: EthLog): BridgeLogsDto {
@@ -53,14 +53,14 @@ data class BridgeLogsDto(
blockNumber = ethLog.blockNumber.toHexString(), blockNumber = ethLog.blockNumber.toHexString(),
address = ethLog.address.encodeHex(), address = ethLog.address.encodeHex(),
data = ethLog.data.encodeHex(), data = ethLog.data.encodeHex(),
topics = ethLog.topics.map { it.encodeHex() } topics = ethLog.topics.map { it.encodeHex() },
) )
} }
} }
} }
internal class ExecutionProofRequestDtoMapper( internal class ExecutionProofRequestDtoMapper(
private val encoder: BlockEncoder = BlockRLPEncoder private val encoder: BlockEncoder = BlockRLPEncoder,
) : (BatchExecutionProofRequestV1) -> SafeFuture<BatchExecutionProofRequestDto> { ) : (BatchExecutionProofRequestV1) -> SafeFuture<BatchExecutionProofRequestDto> {
override fun invoke(request: BatchExecutionProofRequestV1): SafeFuture<BatchExecutionProofRequestDto> { override fun invoke(request: BatchExecutionProofRequestV1): SafeFuture<BatchExecutionProofRequestDto> {
val blocksData = request.blocks.map { block -> val blocksData = request.blocks.map { block ->
@@ -79,8 +79,8 @@ internal class ExecutionProofRequestDtoMapper(
tracesEngineVersion = request.tracesResponse.tracesEngineVersion, tracesEngineVersion = request.tracesResponse.tracesEngineVersion,
type2StateManagerVersion = request.type2StateData.zkStateManagerVersion, type2StateManagerVersion = request.type2StateData.zkStateManagerVersion,
zkStateMerkleProof = request.type2StateData.zkStateMerkleProof, zkStateMerkleProof = request.type2StateData.zkStateMerkleProof,
blocksData = blocksData blocksData = blocksData,
) ),
) )
} }
} }
@@ -105,15 +105,15 @@ class FileBasedExecutionProverClientV2(
executionProofRequestFileNameProvider: ProverFileNameProvider = executionProofRequestFileNameProvider: ProverFileNameProvider =
ExecutionProofRequestFileNameProvider( ExecutionProofRequestFileNameProvider(
tracesVersion = tracesVersion, tracesVersion = tracesVersion,
stateManagerVersion = stateManagerVersion stateManagerVersion = stateManagerVersion,
), ),
executionProofResponseFileNameProvider: ProverFileNameProvider = ExecutionProofResponseFileNameProvider executionProofResponseFileNameProvider: ProverFileNameProvider = ExecutionProofResponseFileNameProvider,
) : ) :
GenericFileBasedProverClient< GenericFileBasedProverClient<
BatchExecutionProofRequestV1, BatchExecutionProofRequestV1,
BatchExecutionProofResponse, BatchExecutionProofResponse,
BatchExecutionProofRequestDto, BatchExecutionProofRequestDto,
Any Any,
>( >(
config = config, config = config,
vertx = vertx, vertx = vertx,
@@ -125,19 +125,19 @@ class FileBasedExecutionProverClientV2(
requestMapper = ExecutionProofRequestDtoMapper(), requestMapper = ExecutionProofRequestDtoMapper(),
responseMapper = { throw UnsupportedOperationException("Batch execution proof response shall not be parsed!") }, responseMapper = { throw UnsupportedOperationException("Batch execution proof response shall not be parsed!") },
proofTypeLabel = "batch", proofTypeLabel = "batch",
log = LogManager.getLogger(FileBasedExecutionProverClientV2::class.java) log = LogManager.getLogger(FileBasedExecutionProverClientV2::class.java),
), ),
ExecutionProverClientV2 { ExecutionProverClientV2 {
override fun parseResponse( override fun parseResponse(
responseFilePath: Path, responseFilePath: Path,
proofIndex: ProofIndex proofIndex: ProofIndex,
): SafeFuture<BatchExecutionProofResponse> { ): SafeFuture<BatchExecutionProofResponse> {
return SafeFuture.completedFuture( return SafeFuture.completedFuture(
BatchExecutionProofResponse( BatchExecutionProofResponse(
startBlockNumber = proofIndex.startBlockNumber, startBlockNumber = proofIndex.startBlockNumber,
endBlockNumber = proofIndex.endBlockNumber endBlockNumber = proofIndex.endBlockNumber,
) ),
) )
} }
} }

View File

@@ -21,13 +21,13 @@ data class AggregationProofRequestDto(
val compressionProofs: List<String>, val compressionProofs: List<String>,
val parentAggregationLastBlockTimestamp: Long, val parentAggregationLastBlockTimestamp: Long,
val parentAggregationLastL1RollingHashMessageNumber: Long, val parentAggregationLastL1RollingHashMessageNumber: Long,
val parentAggregationLastL1RollingHash: String val parentAggregationLastL1RollingHash: String,
) { ) {
companion object { companion object {
fun fromDomainObject( fun fromDomainObject(
proofsToAggregate: ProofsToAggregate, proofsToAggregate: ProofsToAggregate,
executionProofResponseFileNameProvider: ProverFileNameProvider, executionProofResponseFileNameProvider: ProverFileNameProvider,
compressionProofResponseFileNameProvider: ProverFileNameProvider compressionProofResponseFileNameProvider: ProverFileNameProvider,
): AggregationProofRequestDto { ): AggregationProofRequestDto {
val executionProofsResponseFiles = proofsToAggregate.executionProofs val executionProofsResponseFiles = proofsToAggregate.executionProofs
.toIntervalList() .toIntervalList()
@@ -35,8 +35,8 @@ data class AggregationProofRequestDto(
executionProofResponseFileNameProvider.getFileName( executionProofResponseFileNameProvider.getFileName(
ProofIndex( ProofIndex(
startBlockNumber = blockInterval.startBlockNumber, startBlockNumber = blockInterval.startBlockNumber,
endBlockNumber = blockInterval.endBlockNumber endBlockNumber = blockInterval.endBlockNumber,
) ),
) )
} }
@@ -46,8 +46,8 @@ data class AggregationProofRequestDto(
ProofIndex( ProofIndex(
startBlockNumber = it.startBlockNumber, startBlockNumber = it.startBlockNumber,
endBlockNumber = it.endBlockNumber, endBlockNumber = it.endBlockNumber,
hash = it.hash hash = it.hash,
) ),
) )
} }
@@ -57,7 +57,7 @@ data class AggregationProofRequestDto(
parentAggregationLastBlockTimestamp = proofsToAggregate.parentAggregationLastBlockTimestamp.epochSeconds, parentAggregationLastBlockTimestamp = proofsToAggregate.parentAggregationLastBlockTimestamp.epochSeconds,
parentAggregationLastL1RollingHashMessageNumber = parentAggregationLastL1RollingHashMessageNumber =
proofsToAggregate.parentAggregationLastL1RollingHashMessageNumber.toLong(), proofsToAggregate.parentAggregationLastL1RollingHashMessageNumber.toLong(),
parentAggregationLastL1RollingHash = proofsToAggregate.parentAggregationLastL1RollingHash.encodeHex() parentAggregationLastL1RollingHash = proofsToAggregate.parentAggregationLastL1RollingHash.encodeHex(),
) )
} }
} }
@@ -65,15 +65,15 @@ data class AggregationProofRequestDto(
internal class AggregationRequestDtoMapper( internal class AggregationRequestDtoMapper(
private val executionProofResponseFileNameProvider: ProverFileNameProvider, private val executionProofResponseFileNameProvider: ProverFileNameProvider,
private val compressionProofResponseFileNameProvider: ProverFileNameProvider private val compressionProofResponseFileNameProvider: ProverFileNameProvider,
) : (ProofsToAggregate) -> SafeFuture<AggregationProofRequestDto> { ) : (ProofsToAggregate) -> SafeFuture<AggregationProofRequestDto> {
override fun invoke(proofsToAggregate: ProofsToAggregate): SafeFuture<AggregationProofRequestDto> { override fun invoke(proofsToAggregate: ProofsToAggregate): SafeFuture<AggregationProofRequestDto> {
return SafeFuture.completedFuture( return SafeFuture.completedFuture(
AggregationProofRequestDto.fromDomainObject( AggregationProofRequestDto.fromDomainObject(
proofsToAggregate, proofsToAggregate,
executionProofResponseFileNameProvider, executionProofResponseFileNameProvider,
compressionProofResponseFileNameProvider compressionProofResponseFileNameProvider,
) ),
) )
} }
} }
@@ -95,13 +95,13 @@ class FileBasedProofAggregationClientV2(
hashFunction: HashFunction = Sha256HashFunction(), hashFunction: HashFunction = Sha256HashFunction(),
executionProofResponseFileNameProvider: ProverFileNameProvider = ExecutionProofResponseFileNameProvider, executionProofResponseFileNameProvider: ProverFileNameProvider = ExecutionProofResponseFileNameProvider,
compressionProofResponseFileNameProvider: ProverFileNameProvider = CompressionProofResponseFileNameProvider, compressionProofResponseFileNameProvider: ProverFileNameProvider = CompressionProofResponseFileNameProvider,
jsonObjectMapper: ObjectMapper = JsonSerialization.proofResponseMapperV1 jsonObjectMapper: ObjectMapper = JsonSerialization.proofResponseMapperV1,
) : ) :
GenericFileBasedProverClient< GenericFileBasedProverClient<
ProofsToAggregate, ProofsToAggregate,
ProofToFinalize, ProofToFinalize,
AggregationProofRequestDto, AggregationProofRequestDto,
ProofToFinalizeJsonResponse ProofToFinalizeJsonResponse,
>( >(
config = config, config = config,
vertx = vertx, vertx = vertx,
@@ -109,18 +109,18 @@ class FileBasedProofAggregationClientV2(
fileReader = FileReader( fileReader = FileReader(
vertx, vertx,
jsonObjectMapper, jsonObjectMapper,
ProofToFinalizeJsonResponse::class.java ProofToFinalizeJsonResponse::class.java,
), ),
requestFileNameProvider = AggregationProofFileNameProvider, requestFileNameProvider = AggregationProofFileNameProvider,
responseFileNameProvider = AggregationProofFileNameProvider, responseFileNameProvider = AggregationProofFileNameProvider,
proofIndexProvider = createProofIndexProviderFn(hashFunction), proofIndexProvider = createProofIndexProviderFn(hashFunction),
requestMapper = AggregationRequestDtoMapper( requestMapper = AggregationRequestDtoMapper(
executionProofResponseFileNameProvider = executionProofResponseFileNameProvider, executionProofResponseFileNameProvider = executionProofResponseFileNameProvider,
compressionProofResponseFileNameProvider = compressionProofResponseFileNameProvider compressionProofResponseFileNameProvider = compressionProofResponseFileNameProvider,
), ),
responseMapper = ProofToFinalizeJsonResponse::toDomainObject, responseMapper = ProofToFinalizeJsonResponse::toDomainObject,
proofTypeLabel = "aggregation", proofTypeLabel = "aggregation",
log = LogManager.getLogger(this::class.java) log = LogManager.getLogger(this::class.java),
), ),
ProofAggregationProverClientV2 { ProofAggregationProverClientV2 {
@@ -128,20 +128,20 @@ class FileBasedProofAggregationClientV2(
fun createProofIndexProviderFn( fun createProofIndexProviderFn(
hashFunction: HashFunction, hashFunction: HashFunction,
executionProofResponseFileNameProvider: ProverFileNameProvider = ExecutionProofResponseFileNameProvider, executionProofResponseFileNameProvider: ProverFileNameProvider = ExecutionProofResponseFileNameProvider,
compressionProofResponseFileNameProvider: ProverFileNameProvider = CompressionProofResponseFileNameProvider compressionProofResponseFileNameProvider: ProverFileNameProvider = CompressionProofResponseFileNameProvider,
): (ProofsToAggregate) -> ProofIndex { ): (ProofsToAggregate) -> ProofIndex {
return { request: ProofsToAggregate -> return { request: ProofsToAggregate ->
val requestDto = AggregationProofRequestDto.fromDomainObject( val requestDto = AggregationProofRequestDto.fromDomainObject(
proofsToAggregate = request, proofsToAggregate = request,
executionProofResponseFileNameProvider = executionProofResponseFileNameProvider, executionProofResponseFileNameProvider = executionProofResponseFileNameProvider,
compressionProofResponseFileNameProvider = compressionProofResponseFileNameProvider compressionProofResponseFileNameProvider = compressionProofResponseFileNameProvider,
) )
val hash = hashRequest(hashFunction, requestDto) val hash = hashRequest(hashFunction, requestDto)
ProofIndex( ProofIndex(
startBlockNumber = request.startBlockNumber, startBlockNumber = request.startBlockNumber,
endBlockNumber = request.endBlockNumber, endBlockNumber = request.endBlockNumber,
hash = hash hash = hash,
) )
} }
} }

View File

@@ -28,13 +28,13 @@ open class GenericFileBasedProverClient<Request, Response, RequestDto, ResponseD
private val responseFileNameProvider: ProverFileNameProvider, private val responseFileNameProvider: ProverFileNameProvider,
private val fileMonitor: FileMonitor = FileMonitor( private val fileMonitor: FileMonitor = FileMonitor(
vertx, vertx,
FileMonitor.Config(config.pollingInterval, config.pollingTimeout) FileMonitor.Config(config.pollingInterval, config.pollingTimeout),
), ),
private val proofIndexProvider: (Request) -> ProofIndex = ::blockIntervalProofIndex, private val proofIndexProvider: (Request) -> ProofIndex = ::blockIntervalProofIndex,
private val requestMapper: (Request) -> SafeFuture<RequestDto>, private val requestMapper: (Request) -> SafeFuture<RequestDto>,
private val responseMapper: (ResponseDto) -> Response, private val responseMapper: (ResponseDto) -> Response,
private val proofTypeLabel: String, private val proofTypeLabel: String,
private val log: Logger = LogManager.getLogger(GenericFileBasedProverClient::class.java) private val log: Logger = LogManager.getLogger(GenericFileBasedProverClient::class.java),
) : Supplier<Number> ) : Supplier<Number>
where Request : BlockInterval, where Request : BlockInterval,
Response : Any, Response : Any,
@@ -62,7 +62,7 @@ open class GenericFileBasedProverClient<Request, Response, RequestDto, ResponseD
"request already proven: {}={} reusedResponse={}", "request already proven: {}={} reusedResponse={}",
proofTypeLabel, proofTypeLabel,
proofIndex.intervalString(), proofIndex.intervalString(),
responseFilePath responseFilePath,
) )
SafeFuture.completedFuture(responseFilePath) SafeFuture.completedFuture(responseFilePath)
} else { } else {
@@ -74,7 +74,7 @@ open class GenericFileBasedProverClient<Request, Response, RequestDto, ResponseD
"request already in file system: {}={} reusedRequest={}", "request already in file system: {}={} reusedRequest={}",
proofTypeLabel, proofTypeLabel,
proofIndex.intervalString(), proofIndex.intervalString(),
requestFileFound requestFileFound,
) )
SafeFuture.completedFuture(Unit) SafeFuture.completedFuture(Unit)
} else { } else {
@@ -83,7 +83,7 @@ open class GenericFileBasedProverClient<Request, Response, RequestDto, ResponseD
fileWriter.write( fileWriter.write(
proofRequestDto, proofRequestDto,
requestFilePath, requestFilePath,
config.inprogressRequestWritingSuffix config.inprogressRequestWritingSuffix,
).thenApply { ).thenApply {
Unit Unit
} }
@@ -104,13 +104,13 @@ open class GenericFileBasedProverClient<Request, Response, RequestDto, ResponseD
proofTypeLabel, proofTypeLabel,
proofIndex.intervalString(), proofIndex.intervalString(),
it.message, it.message,
it it,
) )
} }
} }
private fun waitForResponse( private fun waitForResponse(
responseFilePath: Path responseFilePath: Path,
): SafeFuture<Path> { ): SafeFuture<Path> {
return fileMonitor.monitor(responseFilePath).thenCompose { return fileMonitor.monitor(responseFilePath).thenCompose {
if (it is Err) { if (it is Err) {
@@ -130,17 +130,17 @@ open class GenericFileBasedProverClient<Request, Response, RequestDto, ResponseD
} }
private fun findRequestFileIfAlreadyInFileSystem( private fun findRequestFileIfAlreadyInFileSystem(
requestFileName: String requestFileName: String,
): SafeFuture<String?> { ): SafeFuture<String?> {
return fileMonitor.findFile( return fileMonitor.findFile(
directory = config.requestsDirectory, directory = config.requestsDirectory,
pattern = inProgressFilePattern(requestFileName, config.inprogressProvingSuffixPattern) pattern = inProgressFilePattern(requestFileName, config.inprogressProvingSuffixPattern),
) )
} }
protected open fun parseResponse( protected open fun parseResponse(
responseFilePath: Path, responseFilePath: Path,
proofIndex: ProofIndex proofIndex: ProofIndex,
): SafeFuture<Response> { ): SafeFuture<Response> {
return fileReader.read(responseFilePath) return fileReader.read(responseFilePath)
.thenCompose { result -> .thenCompose { result ->
@@ -152,7 +152,7 @@ open class GenericFileBasedProverClient<Request, Response, RequestDto, ResponseD
log.error( log.error(
"Failed to read response file={} errorMessage={}", "Failed to read response file={} errorMessage={}",
responseFilePath, responseFilePath,
errorResponse.message errorResponse.message,
) )
} }
} }
@@ -165,13 +165,13 @@ open class GenericFileBasedProverClient<Request, Response, RequestDto, ResponseD
fun <R : BlockInterval> blockIntervalProofIndex(request: R): ProofIndex { fun <R : BlockInterval> blockIntervalProofIndex(request: R): ProofIndex {
return ProofIndex( return ProofIndex(
startBlockNumber = request.startBlockNumber, startBlockNumber = request.startBlockNumber,
endBlockNumber = request.endBlockNumber endBlockNumber = request.endBlockNumber,
) )
} }
fun createDirectoryIfNotExists( fun createDirectoryIfNotExists(
directory: Path, directory: Path,
log: Logger = LogManager.getLogger(GenericFileBasedProverClient::class.java) log: Logger = LogManager.getLogger(GenericFileBasedProverClient::class.java),
) { ) {
try { try {
if (directory.notExists()) { if (directory.notExists()) {

Some files were not shown because too many files have changed in this diff Show More