mirror of
https://github.com/vacp2p/linea-monorepo.git
synced 2026-01-06 22:23:55 -05:00
[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:
@@ -29,7 +29,7 @@ class LineaL1FinalizationTagUpdaterPlugin : BesuPlugin {
|
||||
service = LineaL1FinalizationUpdaterService(
|
||||
vertx,
|
||||
cliOptions.getConfig(),
|
||||
LineaBesuEngineBlockTagUpdater(blockchainService)
|
||||
LineaBesuEngineBlockTagUpdater(blockchainService),
|
||||
)
|
||||
service.start()
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
data class FinalizationUpdatePollerConfig(
|
||||
val pollingInterval: Duration = 12.seconds,
|
||||
val blockTag: BlockParameter
|
||||
val blockTag: BlockParameter,
|
||||
) {
|
||||
init {
|
||||
require(pollingInterval >= 0.seconds) {
|
||||
@@ -30,18 +30,18 @@ class FinalizationUpdatePoller(
|
||||
private val config: FinalizationUpdatePollerConfig,
|
||||
private val lineaRollup: Web3JLineaRollupSmartContractClientReadOnly,
|
||||
private val finalizationHandler: (ULong) -> CompletableFuture<*>,
|
||||
private val log: Logger = LogManager.getLogger(FinalizationUpdatePoller::class.java)
|
||||
private val log: Logger = LogManager.getLogger(FinalizationUpdatePoller::class.java),
|
||||
) : PeriodicPollingService(
|
||||
vertx = vertx,
|
||||
pollingIntervalMs = config.pollingInterval.inWholeMilliseconds,
|
||||
log = log
|
||||
log = log,
|
||||
) {
|
||||
private val lastFinalizationRef: AtomicReference<ULong> = AtomicReference(null)
|
||||
|
||||
override fun action(): SafeFuture<*> {
|
||||
return AsyncRetryer.retry(
|
||||
vertx,
|
||||
backoffDelay = config.pollingInterval
|
||||
backoffDelay = config.pollingInterval,
|
||||
) {
|
||||
lineaRollup.finalizedL2BlockNumber(config.blockTag)
|
||||
.thenCompose { lineaFinalizedBlockNumber ->
|
||||
@@ -61,7 +61,7 @@ class FinalizationUpdatePoller(
|
||||
if (error.cause is UnsupportedOperationException) {
|
||||
log.error(
|
||||
"\"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()
|
||||
} else {
|
||||
|
||||
@@ -28,7 +28,7 @@ class LineaBesuEngineBlockTagUpdater(private val blockchainService: BlockchainSe
|
||||
log.info(
|
||||
"Linea safe/finalized block update: blockNumber={} blockHash={}",
|
||||
finalizedBlockNumber,
|
||||
blockHash
|
||||
blockHash,
|
||||
)
|
||||
blockchainService.setSafeBlock(blockHash)
|
||||
blockchainService.setFinalizedBlock(blockHash)
|
||||
@@ -40,7 +40,7 @@ class LineaBesuEngineBlockTagUpdater(private val blockchainService: BlockchainSe
|
||||
log.error(
|
||||
"Linea safe/finalized block update failure: Method not supported or not enabled for PoS network: " +
|
||||
"setFinalizedBlock and setSafeBlock",
|
||||
e
|
||||
e,
|
||||
)
|
||||
throw e
|
||||
} catch (e: Exception) {
|
||||
@@ -54,7 +54,7 @@ class LineaBesuEngineBlockTagUpdater(private val blockchainService: BlockchainSe
|
||||
}
|
||||
|
||||
override fun lineaUpdateFinalizedBlockV1(
|
||||
finalizedBlockNumber: Long
|
||||
finalizedBlockNumber: Long,
|
||||
) {
|
||||
val updateSuccess = setFinalizedAndSafeBlock(finalizedBlockNumber)
|
||||
log.debug("Linea safe/finalized block update: blockNumber={} success={}", finalizedBlockNumber, updateSuccess)
|
||||
@@ -62,10 +62,10 @@ class LineaBesuEngineBlockTagUpdater(private val blockchainService: BlockchainSe
|
||||
}
|
||||
|
||||
class LineaL1FinalizationUpdater(
|
||||
private val engineBlockTagUpdater: EngineBlockTagUpdater
|
||||
private val engineBlockTagUpdater: EngineBlockTagUpdater,
|
||||
) {
|
||||
fun handleL1Finalization(
|
||||
finalizedBlockNumber: ULong
|
||||
finalizedBlockNumber: ULong,
|
||||
): CompletableFuture<Unit> {
|
||||
runCatching {
|
||||
engineBlockTagUpdater
|
||||
@@ -80,28 +80,28 @@ class LineaL1FinalizationUpdater(
|
||||
class LineaL1FinalizationUpdaterService(
|
||||
vertx: Vertx,
|
||||
config: PluginConfig,
|
||||
engineBlockTagUpdater: EngineBlockTagUpdater
|
||||
engineBlockTagUpdater: EngineBlockTagUpdater,
|
||||
) : LongRunningService {
|
||||
private val web3j = Web3j.build(
|
||||
HttpService(
|
||||
config.l1RpcEndpoint.toString(),
|
||||
okHttpClientBuilder(LogManager.getLogger("clients.l1")).build()
|
||||
)
|
||||
okHttpClientBuilder(LogManager.getLogger("clients.l1")).build(),
|
||||
),
|
||||
)
|
||||
private val lineaRollup = Web3JLineaRollupSmartContractClientReadOnly(
|
||||
contractAddress = config.l1SmartContractAddress.toHexString(),
|
||||
web3j = web3j
|
||||
web3j = web3j,
|
||||
)
|
||||
private val updater = LineaL1FinalizationUpdater(engineBlockTagUpdater)
|
||||
private val poller = FinalizationUpdatePoller(
|
||||
vertx,
|
||||
FinalizationUpdatePollerConfig(
|
||||
pollingInterval = config.l1PollingInterval,
|
||||
blockTag = BlockParameter.Tag.FINALIZED
|
||||
blockTag = BlockParameter.Tag.FINALIZED,
|
||||
),
|
||||
lineaRollup,
|
||||
updater::handleL1Finalization,
|
||||
LogManager.getLogger(FinalizationUpdatePoller::class.java)
|
||||
LogManager.getLogger(FinalizationUpdatePoller::class.java),
|
||||
)
|
||||
|
||||
override fun start(): CompletableFuture<Unit> {
|
||||
|
||||
@@ -11,7 +11,7 @@ import kotlin.time.toKotlinDuration
|
||||
data class PluginConfig(
|
||||
val l1SmartContractAddress: Address,
|
||||
val l1RpcEndpoint: URL,
|
||||
val l1PollingInterval: kotlin.time.Duration
|
||||
val l1PollingInterval: kotlin.time.Duration,
|
||||
) {
|
||||
init {
|
||||
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"],
|
||||
description = ["L1 smart contract address"],
|
||||
required = true,
|
||||
converter = [AddressConverter::class]
|
||||
converter = [AddressConverter::class],
|
||||
)
|
||||
lateinit var l1SmartContractAddress: Address
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--plugin-linea-l1-rpc-endpoint"],
|
||||
description = ["L1 RPC endpoint"],
|
||||
required = true
|
||||
required = true,
|
||||
)
|
||||
lateinit var l1RpcEndpoint: String
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--plugin-linea-l1-polling-interval"],
|
||||
description = ["L1 polling interval"],
|
||||
required = false
|
||||
required = false,
|
||||
)
|
||||
var l1PollingInterval: Duration = Duration.ofSeconds(12)
|
||||
|
||||
@@ -45,14 +45,14 @@ class PluginCliOptions {
|
||||
return PluginConfig(
|
||||
l1SmartContractAddress = l1SmartContractAddress,
|
||||
l1RpcEndpoint = URI(l1RpcEndpoint).toURL(),
|
||||
l1PollingInterval = l1PollingInterval.toKotlinDuration()
|
||||
l1PollingInterval = l1PollingInterval.toKotlinDuration(),
|
||||
)
|
||||
}
|
||||
|
||||
class AddressConverter : CommandLine.ITypeConverter<Address> {
|
||||
override fun convert(value: String): Address {
|
||||
return Address.fromHexString(value) ?: throw CommandLine.TypeConversionException(
|
||||
"Invalid address: $value"
|
||||
"Invalid address: $value",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
class FakeEngineBlockTagUpdater : EngineBlockTagUpdater {
|
||||
override fun lineaUpdateFinalizedBlockV1(
|
||||
finalizedBlockNumber: Long
|
||||
finalizedBlockNumber: Long,
|
||||
) {
|
||||
println("Linea finalized block update: blockNumber=$finalizedBlockNumber")
|
||||
}
|
||||
@@ -23,7 +23,7 @@ fun main() {
|
||||
val config = PluginConfig(
|
||||
l1RpcEndpoint = URI("https://mainnet.infura.io/v3/$infuraAppKey").toURL(),
|
||||
l1SmartContractAddress = Address.fromHexString("0xd19d4B5d358258f05D7B411E21A1460D11B0876F"),
|
||||
l1PollingInterval = 1.seconds
|
||||
l1PollingInterval = 1.seconds,
|
||||
)
|
||||
val service = LineaL1FinalizationUpdaterService(vertx, config, FakeEngineBlockTagUpdater())
|
||||
service.start().get()
|
||||
|
||||
@@ -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 {
|
||||
dependsOn checkLicense
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture
|
||||
|
||||
data class StateRecoveryStatus(
|
||||
val headBlockNumber: ULong,
|
||||
val stateRecoverStartBlockNumber: ULong?
|
||||
val stateRecoverStartBlockNumber: ULong?,
|
||||
)
|
||||
interface ExecutionLayerClient {
|
||||
fun getBlockNumberAndHash(blockParameter: BlockParameter): SafeFuture<BlockNumberAndHash>
|
||||
|
||||
@@ -24,20 +24,20 @@ class InMemoryRecoveryStatus : RecoveryStatusPersistence {
|
||||
}
|
||||
|
||||
class FileBasedRecoveryStatusPersistence(
|
||||
filePath: Path
|
||||
filePath: Path,
|
||||
) : RecoveryStatusPersistence {
|
||||
// A little future proofing in case we need to change the file format in the future
|
||||
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(
|
||||
val version: FileVersion,
|
||||
val recoveryStatus: RecoveryStatusV1Dto?
|
||||
val recoveryStatus: RecoveryStatusV1Dto?,
|
||||
)
|
||||
|
||||
private data class RecoveryStatusV1Dto(
|
||||
val recoveryStartBlockNumber: ULong
|
||||
val recoveryStartBlockNumber: ULong,
|
||||
)
|
||||
private val objectMapper = jacksonObjectMapper()
|
||||
private val file = filePath.toFile()
|
||||
@@ -46,8 +46,8 @@ class FileBasedRecoveryStatusPersistence(
|
||||
private fun saveToFile(status: RecoveryStatusV1Dto?) {
|
||||
file.writeText(
|
||||
objectMapper.writeValueAsString(
|
||||
RecoveryStatusEnvelopeDto(FileVersion.V1, status)
|
||||
)
|
||||
RecoveryStatusEnvelopeDto(FileVersion.V1, status),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class FileRecoveryStatusPersistenceTest {
|
||||
|
||||
@Test
|
||||
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"))
|
||||
assertThat(recoveryStatusPersistence.getRecoveryStartBlockNumber()).isNull()
|
||||
@@ -21,7 +21,7 @@ class FileRecoveryStatusPersistenceTest {
|
||||
|
||||
@Test
|
||||
fun `should return the saved recovery start block number`(
|
||||
@TempDir tempDir: Path
|
||||
@TempDir tempDir: Path,
|
||||
) {
|
||||
FileBasedRecoveryStatusPersistence(tempDir.resolve("recovery-status.json"))
|
||||
.also { persistence ->
|
||||
@@ -46,7 +46,7 @@ class FileRecoveryStatusPersistenceTest {
|
||||
|
||||
@Test
|
||||
fun `shall throw when it cannot create the file`(
|
||||
@TempDir tempDir: Path
|
||||
@TempDir tempDir: Path,
|
||||
) {
|
||||
val dirWithoutWritePermissions = tempDir.resolve("dir-without-write-permissions")
|
||||
|
||||
@@ -64,7 +64,7 @@ class FileRecoveryStatusPersistenceTest {
|
||||
|
||||
@Test
|
||||
fun `should throw error when file version is not supported`(
|
||||
@TempDir tempDir: Path
|
||||
@TempDir tempDir: Path,
|
||||
) {
|
||||
val invalidJsonPayload = """
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@ data class BlockHeaderFromL1RecoveredData(
|
||||
val coinbase: ByteArray,
|
||||
val blockTimestamp: Instant,
|
||||
val gasLimit: ULong,
|
||||
val difficulty: ULong
|
||||
val difficulty: ULong,
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
@@ -51,7 +51,7 @@ data class BlockHeaderFromL1RecoveredData(
|
||||
|
||||
data class BlockFromL1RecoveredData(
|
||||
val header: BlockHeaderFromL1RecoveredData,
|
||||
val transactions: List<TransactionFromL1RecoveredData>
|
||||
val transactions: List<TransactionFromL1RecoveredData>,
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
||||
@@ -14,12 +14,12 @@ data class TransactionFromL1RecoveredData(
|
||||
val to: ByteArray?,
|
||||
val value: BigInteger,
|
||||
val data: ByteArray?,
|
||||
val accessList: List<AccessTuple>?
|
||||
val accessList: List<AccessTuple>?,
|
||||
) {
|
||||
|
||||
data class AccessTuple(
|
||||
val address: ByteArray,
|
||||
val storageKeys: List<ByteArray>
|
||||
val storageKeys: List<ByteArray>,
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
||||
@@ -24,18 +24,18 @@ interface BlobDecompressorAndDeserializer {
|
||||
*/
|
||||
fun decompress(
|
||||
startBlockNumber: ULong,
|
||||
blobs: List<ByteArray>
|
||||
blobs: List<ByteArray>,
|
||||
): SafeFuture<List<BlockFromL1RecoveredData>>
|
||||
}
|
||||
|
||||
data class BlockHeaderStaticFields(
|
||||
val coinbase: ByteArray,
|
||||
val gasLimit: ULong = 2_000_000_000UL,
|
||||
val difficulty: ULong = 2UL
|
||||
val difficulty: ULong = 2UL,
|
||||
) {
|
||||
companion object {
|
||||
val localDev = BlockHeaderStaticFields(
|
||||
coinbase = "0x6d976c9b8ceee705d4fe8699b44e5eb58242f484".decodeHex()
|
||||
coinbase = "0x6d976c9b8ceee705d4fe8699b44e5eb58242f484".decodeHex(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -69,11 +69,11 @@ class BlobDecompressorToDomainV1(
|
||||
val staticFields: BlockHeaderStaticFields,
|
||||
val vertx: Vertx,
|
||||
val decoder: BinaryDecoder<Block> = BesuRlpBlobDecoder,
|
||||
val logger: Logger = LogManager.getLogger(BlobDecompressorToDomainV1::class.java)
|
||||
val logger: Logger = LogManager.getLogger(BlobDecompressorToDomainV1::class.java),
|
||||
) : BlobDecompressorAndDeserializer {
|
||||
override fun decompress(
|
||||
startBlockNumber: ULong,
|
||||
blobs: List<ByteArray>
|
||||
blobs: List<ByteArray>,
|
||||
): SafeFuture<List<BlockFromL1RecoveredData>> {
|
||||
var blockNumber = startBlockNumber
|
||||
val startTime = Clock.System.now()
|
||||
@@ -89,7 +89,7 @@ class BlobDecompressorToDomainV1(
|
||||
coinbase = staticFields.coinbase,
|
||||
blockTimestamp = Instant.fromEpochSeconds(block.header.timestamp),
|
||||
gasLimit = this.staticFields.gasLimit,
|
||||
difficulty = this.staticFields.difficulty
|
||||
difficulty = this.staticFields.difficulty,
|
||||
)
|
||||
val transactions = block.body.transactions.map { transaction ->
|
||||
TransactionFromL1RecoveredData(
|
||||
@@ -106,14 +106,14 @@ class BlobDecompressorToDomainV1(
|
||||
accessList = transaction.accessList.getOrNull()?.map { accessTuple ->
|
||||
TransactionFromL1RecoveredData.AccessTuple(
|
||||
address = accessTuple.address.toArray(),
|
||||
storageKeys = accessTuple.storageKeys.map { it.toArray() }
|
||||
storageKeys = accessTuple.storageKeys.map { it.toArray() },
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
BlockFromL1RecoveredData(
|
||||
header = header,
|
||||
transactions = transactions
|
||||
transactions = transactions,
|
||||
)
|
||||
}
|
||||
}.thenPeek {
|
||||
@@ -122,7 +122,7 @@ class BlobDecompressorToDomainV1(
|
||||
"blobs decompressed and serialized: duration={} blobsCount={} blocks={}",
|
||||
endTime - startTime,
|
||||
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>> {
|
||||
return vertx.executeBlocking(
|
||||
Callable { RLP.decodeList(blocksRLP).map(decoder::decode) },
|
||||
false
|
||||
false,
|
||||
)
|
||||
.onFailure(logger::error)
|
||||
.toSafeFuture()
|
||||
|
||||
@@ -10,7 +10,7 @@ import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
data class ImportResult(
|
||||
val blockNumber: ULong,
|
||||
val zkStateRootHash: ByteArray
|
||||
val zkStateRootHash: ByteArray,
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
@@ -39,7 +39,7 @@ class BlockImporterAndStateVerifierV1(
|
||||
private val vertx: Vertx,
|
||||
private val elClient: ExecutionLayerClient,
|
||||
private val stateManagerClient: StateManagerClientV1,
|
||||
private val stateManagerImportTimeoutPerBlock: Duration
|
||||
private val stateManagerImportTimeoutPerBlock: Duration,
|
||||
) : BlockImporterAndStateVerifier {
|
||||
override fun importBlocks(blocks: List<BlockFromL1RecoveredData>): SafeFuture<ImportResult> {
|
||||
val sortedBlocks = blocks.sortedBy { it.header.blockNumber }
|
||||
@@ -49,20 +49,20 @@ class BlockImporterAndStateVerifierV1(
|
||||
.thenCompose {
|
||||
getBlockStateRootHash(
|
||||
blockNumber = lastBlockNumber,
|
||||
timeout = stateManagerImportTimeoutPerBlock.times(blocks.size)
|
||||
timeout = stateManagerImportTimeoutPerBlock.times(blocks.size),
|
||||
)
|
||||
}
|
||||
.thenApply { stateRootHash ->
|
||||
ImportResult(
|
||||
blockNumber = lastBlockNumber,
|
||||
zkStateRootHash = stateRootHash
|
||||
zkStateRootHash = stateRootHash,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBlockStateRootHash(
|
||||
blockNumber: ULong,
|
||||
timeout: Duration
|
||||
timeout: Duration,
|
||||
): SafeFuture<ByteArray> {
|
||||
return AsyncRetryer
|
||||
.retry(
|
||||
@@ -70,7 +70,7 @@ class BlockImporterAndStateVerifierV1(
|
||||
backoffDelay = 1.seconds,
|
||||
timeout = timeout,
|
||||
stopRetriesPredicate = { headBlockNumber -> headBlockNumber >= blockNumber },
|
||||
action = { stateManagerClient.rollupGetHeadBlockNumber() }
|
||||
action = { stateManagerClient.rollupGetHeadBlockNumber() },
|
||||
)
|
||||
.thenCompose {
|
||||
stateManagerClient.rollupGetStateMerkleProof(BlockInterval(blockNumber, blockNumber))
|
||||
|
||||
@@ -12,7 +12,7 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture
|
||||
data class DataSubmittedV3(
|
||||
val parentShnarf: ByteArray,
|
||||
val shnarf: ByteArray,
|
||||
val finalStateRootHash: ByteArray
|
||||
val finalStateRootHash: ByteArray,
|
||||
) {
|
||||
companion object {
|
||||
val topic = "0x55f4c645c36aa5cd3f443d6be44d7a7a5df9d2100d7139dfc69d4289ee072319"
|
||||
@@ -22,9 +22,9 @@ data class DataSubmittedV3(
|
||||
event = DataSubmittedV3(
|
||||
parentShnarf = ethLog.data.sliceOf32(0),
|
||||
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,
|
||||
val shnarf: ByteArray,
|
||||
val parentStateRootHash: ByteArray,
|
||||
val finalStateRootHash: ByteArray
|
||||
val finalStateRootHash: ByteArray,
|
||||
) : BlockInterval {
|
||||
companion object {
|
||||
val topic = "0xa0262dc79e4ccb71ceac8574ae906311ae338aa4a2044fd4ec4b99fad5ab60cb"
|
||||
@@ -81,9 +81,9 @@ data class DataFinalizedV3(
|
||||
endBlockNumber = ethLog.topics[2].toULongFromLast8Bytes(),
|
||||
shnarf = ethLog.topics[3],
|
||||
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(
|
||||
val dataSubmittedEvents: List<EthLogEvent<DataSubmittedV3>>,
|
||||
val dataFinalizedEvent: EthLogEvent<DataFinalizedV3>
|
||||
val dataFinalizedEvent: EthLogEvent<DataFinalizedV3>,
|
||||
)
|
||||
|
||||
interface LineaRollupSubmissionEventsClient {
|
||||
fun findFinalizationAndDataSubmissionV3Events(
|
||||
fromL1BlockNumber: BlockParameter,
|
||||
finalizationStartBlockNumber: ULong
|
||||
finalizationStartBlockNumber: ULong,
|
||||
): SafeFuture<FinalizationAndDataEventsV3?>
|
||||
|
||||
fun findFinalizationAndDataSubmissionV3EventsContainingL2BlockNumber(
|
||||
fromL1BlockNumber: BlockParameter,
|
||||
l2BlockNumber: ULong
|
||||
l2BlockNumber: ULong,
|
||||
): SafeFuture<FinalizationAndDataEventsV3?>
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class LineaSubmissionEventsClientImpl(
|
||||
private val logsSearcher: EthLogsSearcher,
|
||||
private val smartContractAddress: String,
|
||||
private val l1LatestSearchBlock: BlockParameter = BlockParameter.Tag.FINALIZED,
|
||||
private val logsBlockChunkSize: Int
|
||||
private val logsBlockChunkSize: Int,
|
||||
) : LineaRollupSubmissionEventsClient {
|
||||
init {
|
||||
require(logsBlockChunkSize > 0) { "logsBlockChunkSize=$logsBlockChunkSize must be greater than 0" }
|
||||
@@ -21,7 +21,7 @@ class LineaSubmissionEventsClientImpl(
|
||||
|
||||
private fun findDataFinalizedEventContainingBlock(
|
||||
fromBlock: BlockParameter,
|
||||
l2BlockNumber: ULong
|
||||
l2BlockNumber: ULong,
|
||||
): SafeFuture<EthLogEvent<DataFinalizedV3>?> {
|
||||
return logsSearcher.findLog(
|
||||
fromBlock = fromBlock,
|
||||
@@ -36,18 +36,18 @@ class LineaSubmissionEventsClientImpl(
|
||||
l2BlockNumber > event.endBlockNumber -> SearchDirection.FORWARD
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
},
|
||||
).thenApply { it?.let { DataFinalizedV3.fromEthLog(it) } }
|
||||
}
|
||||
|
||||
override fun findFinalizationAndDataSubmissionV3Events(
|
||||
fromL1BlockNumber: BlockParameter,
|
||||
finalizationStartBlockNumber: ULong
|
||||
finalizationStartBlockNumber: ULong,
|
||||
): SafeFuture<FinalizationAndDataEventsV3?> {
|
||||
return findDataFinalizedV3Event(
|
||||
fromL1BlockNumber = fromL1BlockNumber,
|
||||
toL1BlockNumber = l1LatestSearchBlock,
|
||||
startBlockNumber = finalizationStartBlockNumber
|
||||
startBlockNumber = finalizationStartBlockNumber,
|
||||
)
|
||||
.thenCompose { finalizationEvent ->
|
||||
finalizationEvent
|
||||
@@ -63,7 +63,7 @@ class LineaSubmissionEventsClientImpl(
|
||||
|
||||
override fun findFinalizationAndDataSubmissionV3EventsContainingL2BlockNumber(
|
||||
fromL1BlockNumber: BlockParameter,
|
||||
l2BlockNumber: ULong
|
||||
l2BlockNumber: ULong,
|
||||
): SafeFuture<FinalizationAndDataEventsV3?> {
|
||||
return findDataFinalizedEventContainingBlock(fromL1BlockNumber, l2BlockNumber)
|
||||
.thenCompose { finalizationEvent ->
|
||||
@@ -82,7 +82,7 @@ class LineaSubmissionEventsClientImpl(
|
||||
fromL1BlockNumber: BlockParameter,
|
||||
toL1BlockNumber: BlockParameter,
|
||||
startBlockNumber: ULong? = null,
|
||||
endBlockNumber: ULong? = null
|
||||
endBlockNumber: ULong? = null,
|
||||
): SafeFuture<EthLogEvent<DataFinalizedV3>?> {
|
||||
assert(startBlockNumber != null || endBlockNumber != null) {
|
||||
"Either startBlockNumber or endBlockNumber must be provided"
|
||||
@@ -104,8 +104,8 @@ class LineaSubmissionEventsClientImpl(
|
||||
topics = listOf(
|
||||
DataFinalizedV3.topic,
|
||||
startBlockNumber?.toHexStringUInt256(),
|
||||
endBlockNumber?.toHexStringUInt256()
|
||||
)
|
||||
endBlockNumber?.toHexStringUInt256(),
|
||||
),
|
||||
).thenCompose { rawLogs ->
|
||||
val finalizedEvents = rawLogs.map(DataFinalizedV3::fromEthLog)
|
||||
|
||||
@@ -122,7 +122,7 @@ class LineaSubmissionEventsClientImpl(
|
||||
}
|
||||
|
||||
private fun findAggregationDataSubmittedV3Events(
|
||||
finalizationEvent: EthLogEvent<DataFinalizedV3>
|
||||
finalizationEvent: EthLogEvent<DataFinalizedV3>,
|
||||
): SafeFuture<List<EthLogEvent<DataSubmittedV3>>> {
|
||||
val dataEvents = mutableListOf<EthLogEvent<DataSubmittedV3>>()
|
||||
val futureResult = SafeFuture<List<EthLogEvent<DataSubmittedV3>>>()
|
||||
@@ -140,7 +140,7 @@ class LineaSubmissionEventsClientImpl(
|
||||
findDataSubmittedV3EventByShnarf(
|
||||
fromL1BlockParameter = BlockParameter.Tag.EARLIEST,
|
||||
tol1BlockParameter = dataSubmission.log.blockNumber.toLong().toBlockParameter(),
|
||||
shnarf = dataSubmission.event.parentShnarf
|
||||
shnarf = dataSubmission.event.parentShnarf,
|
||||
).thenPeek(::fetchParentDataSubmission)
|
||||
}
|
||||
}
|
||||
@@ -148,7 +148,7 @@ class LineaSubmissionEventsClientImpl(
|
||||
getDataSubmittedV3EventByShnarf(
|
||||
fromL1BlockParameter = BlockParameter.Tag.EARLIEST,
|
||||
tol1BlockParameter = finalizationEvent.log.blockNumber.toLong().toBlockParameter(),
|
||||
shnarf = finalizationEvent.event.shnarf
|
||||
shnarf = finalizationEvent.event.shnarf,
|
||||
).thenPeek(::fetchParentDataSubmission)
|
||||
|
||||
return futureResult
|
||||
@@ -157,7 +157,7 @@ class LineaSubmissionEventsClientImpl(
|
||||
private fun getDataSubmittedV3EventByShnarf(
|
||||
fromL1BlockParameter: BlockParameter,
|
||||
tol1BlockParameter: BlockParameter,
|
||||
shnarf: ByteArray
|
||||
shnarf: ByteArray,
|
||||
): SafeFuture<EthLogEvent<DataSubmittedV3>> {
|
||||
return findDataSubmittedV3EventByShnarf(fromL1BlockParameter, tol1BlockParameter, shnarf)
|
||||
.thenApply { event ->
|
||||
@@ -168,7 +168,7 @@ class LineaSubmissionEventsClientImpl(
|
||||
private fun findDataSubmittedV3EventByShnarf(
|
||||
fromL1BlockParameter: BlockParameter,
|
||||
tol1BlockParameter: BlockParameter,
|
||||
shnarf: ByteArray
|
||||
shnarf: ByteArray,
|
||||
): SafeFuture<EthLogEvent<DataSubmittedV3>?> {
|
||||
return logsSearcher
|
||||
.getLogs(
|
||||
@@ -177,8 +177,8 @@ class LineaSubmissionEventsClientImpl(
|
||||
address = smartContractAddress,
|
||||
topics = listOf(
|
||||
DataSubmittedV3.topic,
|
||||
shnarf.encodeHex()
|
||||
)
|
||||
shnarf.encodeHex(),
|
||||
),
|
||||
)
|
||||
.thenApply { rawLogs ->
|
||||
val events = rawLogs.map(DataSubmittedV3::fromEthLog)
|
||||
|
||||
@@ -12,28 +12,28 @@ import kotlin.time.Duration.Companion.seconds
|
||||
class LookBackBlockHashesFetcher(
|
||||
private val vertx: Vertx,
|
||||
private val elClient: ExecutionLayerClient,
|
||||
private val submissionsFetcher: SubmissionsFetchingTask
|
||||
private val submissionsFetcher: SubmissionsFetchingTask,
|
||||
) {
|
||||
fun getLookBackHashes(
|
||||
status: StateRecoveryStatus
|
||||
status: StateRecoveryStatus,
|
||||
): SafeFuture<Map<ULong, ByteArray>> {
|
||||
val intervals = lookbackFetchingIntervals(
|
||||
headBlockNumber = status.headBlockNumber,
|
||||
recoveryStartBlockNumber = status.stateRecoverStartBlockNumber,
|
||||
lookbackWindow = 256UL
|
||||
lookbackWindow = 256UL,
|
||||
)
|
||||
|
||||
return SafeFuture.collectAll(
|
||||
listOf(
|
||||
intervals.elInterval?.let(::getLookBackHashesFromLocalEl) ?: SafeFuture.completedFuture(emptyMap()),
|
||||
intervals.l1Interval?.let(::getLookBackHashesFromL1) ?: SafeFuture.completedFuture(emptyMap())
|
||||
).stream()
|
||||
intervals.l1Interval?.let(::getLookBackHashesFromL1) ?: SafeFuture.completedFuture(emptyMap()),
|
||||
).stream(),
|
||||
)
|
||||
.thenApply { (blockHashesFromEl, blockHashesFromL1) -> blockHashesFromEl + blockHashesFromL1 }
|
||||
}
|
||||
|
||||
fun getLookBackHashesFromLocalEl(
|
||||
blockInterval: BlockInterval
|
||||
blockInterval: BlockInterval,
|
||||
): SafeFuture<Map<ULong, ByteArray>> {
|
||||
return SafeFuture
|
||||
.collectAll(blockInterval.blocksRange.map { elClient.getBlockNumberAndHash(it.toBlockParameter()) }.stream())
|
||||
@@ -43,7 +43,7 @@ class LookBackBlockHashesFetcher(
|
||||
}
|
||||
|
||||
fun getLookBackHashesFromL1(
|
||||
blockInterval: BlockInterval
|
||||
blockInterval: BlockInterval,
|
||||
): SafeFuture<Map<ULong, ByteArray>> {
|
||||
return AsyncRetryer.retry(
|
||||
vertx,
|
||||
@@ -51,7 +51,7 @@ class LookBackBlockHashesFetcher(
|
||||
stopRetriesPredicate = { submissions ->
|
||||
submissions.isNotEmpty() &&
|
||||
submissions.last().submissionEvents.dataFinalizedEvent.event.endBlockNumber >= blockInterval.endBlockNumber
|
||||
}
|
||||
},
|
||||
) {
|
||||
// get the data without removing it from the queue
|
||||
// it must still be in the queue until is imported to the EL
|
||||
@@ -75,7 +75,7 @@ class LookBackBlockHashesFetcher(
|
||||
|
||||
fun shallIncreaseQueueLimit(
|
||||
availableSubmissions: List<SubmissionEventsAndData<BlockFromL1RecoveredData>>,
|
||||
blockInterval: BlockInterval
|
||||
blockInterval: BlockInterval,
|
||||
): Boolean {
|
||||
if (availableSubmissions.isEmpty()) {
|
||||
return false
|
||||
|
||||
@@ -6,7 +6,7 @@ import linea.kotlin.minusCoercingUnderflow
|
||||
fun startBlockToFetchFromL1(
|
||||
headBlockNumber: ULong,
|
||||
recoveryStartBlockNumber: ULong?,
|
||||
lookbackWindow: ULong
|
||||
lookbackWindow: ULong,
|
||||
): ULong {
|
||||
if (recoveryStartBlockNumber == null) {
|
||||
return headBlockNumber + 1UL
|
||||
@@ -19,24 +19,24 @@ fun startBlockToFetchFromL1(
|
||||
|
||||
data class FetchingIntervals(
|
||||
val elInterval: BlockInterval?,
|
||||
val l1Interval: BlockInterval?
|
||||
val l1Interval: BlockInterval?,
|
||||
)
|
||||
|
||||
fun lookbackFetchingIntervals(
|
||||
headBlockNumber: ULong,
|
||||
recoveryStartBlockNumber: ULong?,
|
||||
lookbackWindow: ULong
|
||||
lookbackWindow: ULong,
|
||||
): FetchingIntervals {
|
||||
if (recoveryStartBlockNumber == null || recoveryStartBlockNumber > headBlockNumber) {
|
||||
return FetchingIntervals(
|
||||
l1Interval = null,
|
||||
elInterval = BlockInterval(headBlockNumber.minusCoercingUnderflow(lookbackWindow - 1UL), headBlockNumber)
|
||||
elInterval = BlockInterval(headBlockNumber.minusCoercingUnderflow(lookbackWindow - 1UL), headBlockNumber),
|
||||
)
|
||||
}
|
||||
if (headBlockNumber - lookbackWindow > recoveryStartBlockNumber) {
|
||||
return FetchingIntervals(
|
||||
l1Interval = BlockInterval(headBlockNumber.minusCoercingUnderflow(lookbackWindow - 1UL), headBlockNumber),
|
||||
elInterval = null
|
||||
elInterval = null,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ fun lookbackFetchingIntervals(
|
||||
l1Interval = BlockInterval(recoveryStartBlockNumber, headBlockNumber),
|
||||
elInterval = BlockInterval(
|
||||
headBlockNumber.minusCoercingUnderflow(lookbackWindow - 1UL),
|
||||
recoveryStartBlockNumber - 1UL
|
||||
)
|
||||
recoveryStartBlockNumber - 1UL,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ class StateRecoveryApp(
|
||||
private val transactionDetailsClient: TransactionDetailsClient,
|
||||
private val blockHeaderStaticFields: BlockHeaderStaticFields,
|
||||
// configs
|
||||
private val config: Config
|
||||
private val config: Config,
|
||||
) : LongRunningService {
|
||||
data class Config(
|
||||
val smartContractAddress: String,
|
||||
@@ -43,7 +43,7 @@ class StateRecoveryApp(
|
||||
* this is meant for testing purposes, not production
|
||||
*/
|
||||
val overridingRecoveryStartBlockNumber: ULong? = null,
|
||||
val debugForceSyncStopBlockNumber: ULong? = null
|
||||
val debugForceSyncStopBlockNumber: ULong? = null,
|
||||
) {
|
||||
companion object {
|
||||
val lineaMainnet = Config(
|
||||
@@ -53,7 +53,7 @@ class StateRecoveryApp(
|
||||
l1LatestSearchBlock = BlockParameter.Tag.FINALIZED,
|
||||
l1PollingInterval = 12.seconds,
|
||||
l1getLogsChunkSize = 10_000u,
|
||||
executionClientPollingInterval = 2.seconds
|
||||
executionClientPollingInterval = 2.seconds,
|
||||
)
|
||||
val lineaSepolia = Config(
|
||||
smartContractAddress = "0xb218f8a4bc926cf1ca7b3423c154a0d627bdb7e5",
|
||||
@@ -61,7 +61,7 @@ class StateRecoveryApp(
|
||||
l1LatestSearchBlock = BlockParameter.Tag.FINALIZED,
|
||||
l1PollingInterval = 12.seconds,
|
||||
l1getLogsChunkSize = 10_000u,
|
||||
executionClientPollingInterval = 2.seconds
|
||||
executionClientPollingInterval = 2.seconds,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -76,19 +76,19 @@ class StateRecoveryApp(
|
||||
logsSearcher = ethLogsSearcher,
|
||||
smartContractAddress = config.smartContractAddress,
|
||||
l1LatestSearchBlock = config.l1LatestSearchBlock,
|
||||
logsBlockChunkSize = config.l1getLogsChunkSize.toInt()
|
||||
logsBlockChunkSize = config.l1getLogsChunkSize.toInt(),
|
||||
)
|
||||
private val log = LogManager.getLogger(this::class.java)
|
||||
private val blockImporterAndStateVerifier = BlockImporterAndStateVerifierV1(
|
||||
vertx = vertx,
|
||||
elClient = elClient,
|
||||
stateManagerClient = stateManagerClient,
|
||||
stateManagerImportTimeoutPerBlock = 2.seconds
|
||||
stateManagerImportTimeoutPerBlock = 2.seconds,
|
||||
)
|
||||
private val blobDecompressor: BlobDecompressorAndDeserializer = BlobDecompressorToDomainV1(
|
||||
decompressor = GoNativeBlobDecompressorFactory.getInstance(config.blobDecompressorVersion),
|
||||
staticFields = blockHeaderStaticFields,
|
||||
vertx = vertx
|
||||
vertx = vertx,
|
||||
)
|
||||
private val stateSynchronizerService = StateSynchronizerService(
|
||||
vertx = vertx,
|
||||
@@ -100,7 +100,7 @@ class StateRecoveryApp(
|
||||
blobDecompressor = blobDecompressor,
|
||||
blockImporterAndStateVerifier = blockImporterAndStateVerifier,
|
||||
pollingInterval = config.l1PollingInterval,
|
||||
debugForceSyncStopBlockNumber = config.debugForceSyncStopBlockNumber
|
||||
debugForceSyncStopBlockNumber = config.debugForceSyncStopBlockNumber,
|
||||
)
|
||||
val stateRootMismatchFound: Boolean
|
||||
get() = stateSynchronizerService.stateRootMismatchFound
|
||||
@@ -119,7 +119,7 @@ class StateRecoveryApp(
|
||||
updateLabel,
|
||||
newStatus.headBlockNumber,
|
||||
statusBeforeUpdate.stateRecoverStartBlockNumber,
|
||||
newStatus.stateRecoverStartBlockNumber
|
||||
newStatus.stateRecoverStartBlockNumber,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -138,7 +138,7 @@ class StateRecoveryApp(
|
||||
log.info(
|
||||
"starting recovery mode already enabled: stateRecoverStartBlockNumber={} headBlockNumber={}",
|
||||
status.stateRecoverStartBlockNumber,
|
||||
status.headBlockNumber
|
||||
status.headBlockNumber,
|
||||
)
|
||||
SafeFuture.completedFuture(Unit)
|
||||
} else {
|
||||
@@ -153,7 +153,7 @@ class StateRecoveryApp(
|
||||
"L1 lastFinalizedBlockNumber={}",
|
||||
stateRecoverStartBlockNumber,
|
||||
status.headBlockNumber,
|
||||
lastFinalizedBlockNumber
|
||||
lastFinalizedBlockNumber,
|
||||
)
|
||||
elClient.lineaEnableStateRecovery(stateRecoverStartBlockNumber)
|
||||
}.thenApply { }
|
||||
@@ -175,17 +175,17 @@ class StateRecoveryApp(
|
||||
log.info(
|
||||
"node reached recovery target block: stateRecoverStartBlockNumber={} headBlockNumber={}",
|
||||
recoveryStatus.stateRecoverStartBlockNumber,
|
||||
recoveryStatus.headBlockNumber
|
||||
recoveryStatus.headBlockNumber,
|
||||
)
|
||||
} else {
|
||||
log.info(
|
||||
"waiting for node to sync until stateRecoverStartBlockNumber={} - 1, headBlockNumber={}",
|
||||
recoveryStatus.stateRecoverStartBlockNumber,
|
||||
recoveryStatus.headBlockNumber
|
||||
recoveryStatus.headBlockNumber,
|
||||
)
|
||||
}
|
||||
hasReachedTargetBlock
|
||||
}
|
||||
},
|
||||
) {
|
||||
elClient.lineaGetStateRecoveryStatus()
|
||||
}
|
||||
|
||||
@@ -22,11 +22,11 @@ class StateSynchronizerService(
|
||||
private val blockImporterAndStateVerifier: BlockImporterAndStateVerifier,
|
||||
private val pollingInterval: Duration,
|
||||
private val debugForceSyncStopBlockNumber: ULong?,
|
||||
private val log: Logger = LogManager.getLogger(StateSynchronizerService::class.java)
|
||||
private val log: Logger = LogManager.getLogger(StateSynchronizerService::class.java),
|
||||
) : PeriodicPollingService(
|
||||
vertx = vertx,
|
||||
log = log,
|
||||
pollingIntervalMs = pollingInterval.inWholeMilliseconds
|
||||
pollingIntervalMs = pollingInterval.inWholeMilliseconds,
|
||||
) {
|
||||
@get:Synchronized
|
||||
@set:Synchronized
|
||||
@@ -48,7 +48,7 @@ class StateSynchronizerService(
|
||||
val l2StartBlockNumberToFetchInclusive = startBlockToFetchFromL1(
|
||||
headBlockNumber = status.headBlockNumber,
|
||||
recoveryStartBlockNumber = status.stateRecoverStartBlockNumber,
|
||||
lookbackWindow = 256UL
|
||||
lookbackWindow = 256UL,
|
||||
)
|
||||
|
||||
this.blobsFetcherTask = SubmissionsFetchingTask(
|
||||
@@ -63,7 +63,7 @@ class StateSynchronizerService(
|
||||
submissionEventsQueueLimit = 10,
|
||||
compressedBlobsQueueLimit = 10,
|
||||
targetDecompressedBlobsQueueLimit = 10,
|
||||
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber
|
||||
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber,
|
||||
)
|
||||
blobsFetcherTask.start()
|
||||
}
|
||||
@@ -91,7 +91,7 @@ class StateSynchronizerService(
|
||||
val loobackHasheFetcher = LookBackBlockHashesFetcher(
|
||||
vertx = vertx,
|
||||
elClient = elClient,
|
||||
submissionsFetcher = blobsFetcherTask
|
||||
submissionsFetcher = blobsFetcherTask,
|
||||
)
|
||||
|
||||
return this.elClient
|
||||
@@ -116,30 +116,30 @@ class StateSynchronizerService(
|
||||
if (blocksToImport.isEmpty()) {
|
||||
log.debug(
|
||||
"no blocks to import for finalization={}",
|
||||
nexFinalization.submissionEvents.dataFinalizedEvent.event
|
||||
nexFinalization.submissionEvents.dataFinalizedEvent.event,
|
||||
)
|
||||
return@thenCompose SafeFuture.completedFuture(Unit)
|
||||
}
|
||||
|
||||
importBlocksAndAssertStateroot(
|
||||
decompressedBlocksToImport = blocksToImport,
|
||||
dataFinalizedV3 = nexFinalization.submissionEvents.dataFinalizedEvent.event
|
||||
dataFinalizedV3 = nexFinalization.submissionEvents.dataFinalizedEvent.event,
|
||||
)
|
||||
}
|
||||
.thenPeek {
|
||||
blobsFetcherTask.pruneQueueForElementsUpToInclusive(
|
||||
nexFinalization.submissionEvents.dataFinalizedEvent.event.endBlockNumber
|
||||
nexFinalization.submissionEvents.dataFinalizedEvent.event.endBlockNumber,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun importBlocksAndAssertStateroot(
|
||||
decompressedBlocksToImport: List<BlockFromL1RecoveredData>,
|
||||
dataFinalizedV3: DataFinalizedV3
|
||||
dataFinalizedV3: DataFinalizedV3,
|
||||
): SafeFuture<Unit> {
|
||||
val blockInterval = CommonDomainFunctions.blockIntervalString(
|
||||
decompressedBlocksToImport.first().header.blockNumber,
|
||||
decompressedBlocksToImport.last().header.blockNumber
|
||||
decompressedBlocksToImport.last().header.blockNumber,
|
||||
)
|
||||
log.debug("importing blocks={} from finalization={}", blockInterval, dataFinalizedV3.intervalString())
|
||||
return blockImporterAndStateVerifier
|
||||
@@ -151,7 +151,7 @@ class StateSynchronizerService(
|
||||
}
|
||||
|
||||
private fun filterOutBlocksAlreadyImportedAndBeyondStopSync(
|
||||
blocks: List<BlockFromL1RecoveredData>
|
||||
blocks: List<BlockFromL1RecoveredData>,
|
||||
): SafeFuture<List<BlockFromL1RecoveredData>> {
|
||||
return elClient.getBlockNumberAndHash(blockParameter = BlockParameter.Tag.LATEST)
|
||||
.thenApply { headBlock ->
|
||||
@@ -165,14 +165,14 @@ class StateSynchronizerService(
|
||||
|
||||
private fun assertStateMatches(
|
||||
importResult: ImportResult,
|
||||
finalizedV3: DataFinalizedV3
|
||||
finalizedV3: DataFinalizedV3,
|
||||
): SafeFuture<Unit> {
|
||||
if (importResult.blockNumber != finalizedV3.endBlockNumber) {
|
||||
log.info(
|
||||
"cannot compare stateroot: last imported block={} finalization={} debugForceSyncStopBlockNumber={}",
|
||||
importResult.blockNumber,
|
||||
finalizedV3.intervalString(),
|
||||
debugForceSyncStopBlockNumber
|
||||
debugForceSyncStopBlockNumber,
|
||||
)
|
||||
if (importResult.blockNumber == debugForceSyncStopBlockNumber) {
|
||||
// this means debugForceSyncStopBlockNumber was set and we stopped before reaching the target block
|
||||
@@ -183,7 +183,7 @@ class StateSynchronizerService(
|
||||
log.info(
|
||||
"state recovered up to finalization={} zkStateRootHash={}",
|
||||
finalizedV3.intervalString(),
|
||||
importResult.zkStateRootHash.encodeHex()
|
||||
importResult.zkStateRootHash.encodeHex(),
|
||||
)
|
||||
} else {
|
||||
log.error(
|
||||
@@ -193,7 +193,7 @@ class StateSynchronizerService(
|
||||
finalizedV3.intervalString(),
|
||||
importResult.blockNumber,
|
||||
importResult.zkStateRootHash.encodeHex(),
|
||||
finalizedV3.finalStateRootHash.encodeHex()
|
||||
finalizedV3.finalStateRootHash.encodeHex(),
|
||||
)
|
||||
stateRootMismatchFound = true
|
||||
this.stop()
|
||||
|
||||
@@ -18,11 +18,11 @@ internal class BlobDecompressionTask(
|
||||
private val rawBlobsQueue: ConcurrentLinkedQueue<SubmissionEventsAndData<ByteArray>>,
|
||||
private val decompressedBlocksQueue: ConcurrentLinkedQueue<SubmissionEventsAndData<BlockFromL1RecoveredData>>,
|
||||
private val decompressedFinalizationQueueLimit: Supplier<Int>,
|
||||
private val log: Logger = LogManager.getLogger(SubmissionsFetchingTask::class.java)
|
||||
private val log: Logger = LogManager.getLogger(SubmissionsFetchingTask::class.java),
|
||||
) : PeriodicPollingService(
|
||||
vertx = vertx,
|
||||
pollingIntervalMs = pollingInterval.inWholeMilliseconds,
|
||||
log = log
|
||||
log = log,
|
||||
) {
|
||||
override fun action(): SafeFuture<*> {
|
||||
return decompressAndDeserializeBlobs()
|
||||
@@ -38,10 +38,10 @@ internal class BlobDecompressionTask(
|
||||
return blobDecompressor
|
||||
.decompress(
|
||||
startBlockNumber = submissionEventsAndData.submissionEvents.dataFinalizedEvent.event.startBlockNumber,
|
||||
blobs = submissionEventsAndData.data
|
||||
blobs = submissionEventsAndData.data,
|
||||
).thenCompose { decompressedBlocks ->
|
||||
decompressedBlocksQueue.add(
|
||||
SubmissionEventsAndData(submissionEventsAndData.submissionEvents, decompressedBlocks)
|
||||
SubmissionEventsAndData(submissionEventsAndData.submissionEvents, decompressedBlocks),
|
||||
)
|
||||
decompressAndDeserializeBlobs()
|
||||
}
|
||||
|
||||
@@ -19,11 +19,11 @@ internal class BlobsFetchingTask(
|
||||
private val submissionEventsQueue: ConcurrentLinkedQueue<FinalizationAndDataEventsV3>,
|
||||
private val compressedBlobsQueue: ConcurrentLinkedQueue<SubmissionEventsAndData<ByteArray>>,
|
||||
private val compressedBlobsQueueLimit: Int,
|
||||
private val log: Logger = LogManager.getLogger(BlobsFetchingTask::class.java)
|
||||
private val log: Logger = LogManager.getLogger(BlobsFetchingTask::class.java),
|
||||
) : PeriodicPollingService(
|
||||
vertx = vertx,
|
||||
pollingIntervalMs = pollingInterval.inWholeMilliseconds,
|
||||
log = log
|
||||
log = log,
|
||||
) {
|
||||
|
||||
override fun action(): SafeFuture<*> {
|
||||
@@ -50,13 +50,13 @@ internal class BlobsFetchingTask(
|
||||
}
|
||||
|
||||
private fun fetchBlobsOfSubmissionEvents(
|
||||
submissionEvents: FinalizationAndDataEventsV3
|
||||
submissionEvents: FinalizationAndDataEventsV3,
|
||||
): SafeFuture<List<ByteArray>> {
|
||||
return SafeFuture.collectAll(
|
||||
submissionEvents.dataSubmittedEvents
|
||||
.map {
|
||||
transactionDetailsClient.getBlobVersionedHashesByTransactionHash(it.log.transactionHash)
|
||||
}.stream()
|
||||
}.stream(),
|
||||
)
|
||||
.thenCompose { blobsVersionedHashesByTransaction ->
|
||||
blobsFetcher.fetchBlobsByHash(blobsVersionedHashesByTransaction.flatten())
|
||||
|
||||
@@ -24,11 +24,11 @@ internal class SubmissionEventsFetchingTask(
|
||||
private val submissionEventsQueue: ConcurrentLinkedQueue<FinalizationAndDataEventsV3>,
|
||||
private val queueLimit: Int,
|
||||
private val debugForceSyncStopBlockNumber: ULong?,
|
||||
private val log: Logger = LogManager.getLogger(SubmissionEventsFetchingTask::class.java)
|
||||
private val log: Logger = LogManager.getLogger(SubmissionEventsFetchingTask::class.java),
|
||||
) : PeriodicPollingService(
|
||||
vertx = vertx,
|
||||
pollingIntervalMs = l1PollingInterval.inWholeMilliseconds,
|
||||
log = log
|
||||
log = log,
|
||||
) {
|
||||
val latestFetchedFinalization: AtomicReference<EthLogEvent<DataFinalizedV3>> = AtomicReference(null)
|
||||
|
||||
@@ -38,7 +38,7 @@ internal class SubmissionEventsFetchingTask(
|
||||
) {
|
||||
log.debug(
|
||||
"Force stop fetching submission events from L1, reached debugForceSyncStopBlockNumber={}",
|
||||
debugForceSyncStopBlockNumber
|
||||
debugForceSyncStopBlockNumber,
|
||||
)
|
||||
return this.stop()
|
||||
}
|
||||
@@ -51,7 +51,7 @@ internal class SubmissionEventsFetchingTask(
|
||||
// Queue is full, no need to fetch more
|
||||
log.debug(
|
||||
"skipping fetching submission events from L1, internal queue is full size={}",
|
||||
submissionEventsQueue.size
|
||||
submissionEventsQueue.size,
|
||||
)
|
||||
return SafeFuture.completedFuture(Unit)
|
||||
}
|
||||
@@ -74,21 +74,21 @@ internal class SubmissionEventsFetchingTask(
|
||||
return if (latestFetchedFinalization.get() != null) {
|
||||
log.trace(
|
||||
"fetching submission events from L1 startBlockNumber={}",
|
||||
latestFetchedFinalization.get().event.endBlockNumber + 1u
|
||||
latestFetchedFinalization.get().event.endBlockNumber + 1u,
|
||||
)
|
||||
submissionEventsClient.findFinalizationAndDataSubmissionV3Events(
|
||||
fromL1BlockNumber = latestFetchedFinalization.get().log.blockNumber.toBlockParameter(),
|
||||
finalizationStartBlockNumber = latestFetchedFinalization.get().event.endBlockNumber + 1u
|
||||
finalizationStartBlockNumber = latestFetchedFinalization.get().event.endBlockNumber + 1u,
|
||||
)
|
||||
} else {
|
||||
log.trace(
|
||||
"fetching submission events from L1 startBlockNumber={}",
|
||||
l2StartBlockNumber
|
||||
l2StartBlockNumber,
|
||||
)
|
||||
submissionEventsClient
|
||||
.findFinalizationAndDataSubmissionV3EventsContainingL2BlockNumber(
|
||||
fromL1BlockNumber = l1EarliestBlockWithFinalizationThatSupportRecovery,
|
||||
l2BlockNumber = l2StartBlockNumber
|
||||
l2BlockNumber = l2StartBlockNumber,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import kotlin.time.Duration.Companion.seconds
|
||||
*/
|
||||
data class SubmissionEventsAndData<T>(
|
||||
val submissionEvents: FinalizationAndDataEventsV3,
|
||||
val data: List<T>
|
||||
val data: List<T>,
|
||||
)
|
||||
|
||||
class SubmissionsFetchingTask(
|
||||
@@ -44,11 +44,11 @@ class SubmissionsFetchingTask(
|
||||
private val compressedBlobsQueueLimit: Int,
|
||||
private val targetDecompressedBlobsQueueLimit: Int,
|
||||
private val debugForceSyncStopBlockNumber: ULong?,
|
||||
private val log: Logger = LogManager.getLogger(SubmissionsFetchingTask::class.java)
|
||||
private val log: Logger = LogManager.getLogger(SubmissionsFetchingTask::class.java),
|
||||
) : PeriodicPollingService(
|
||||
vertx = vertx,
|
||||
pollingIntervalMs = l1PollingInterval.inWholeMilliseconds,
|
||||
log = log
|
||||
log = log,
|
||||
) {
|
||||
init {
|
||||
require(submissionEventsQueueLimit >= 1) {
|
||||
@@ -84,7 +84,7 @@ class SubmissionsFetchingTask(
|
||||
l2StartBlockNumber = l2StartBlockNumberToFetchInclusive,
|
||||
submissionEventsQueue = submissionEventsQueue,
|
||||
queueLimit = submissionEventsQueueLimit,
|
||||
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber
|
||||
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber,
|
||||
)
|
||||
private val blobFetchingTask = BlobsFetchingTask(
|
||||
vertx = vertx,
|
||||
@@ -93,7 +93,7 @@ class SubmissionsFetchingTask(
|
||||
blobsFetcher = blobsFetcher,
|
||||
transactionDetailsClient = transactionDetailsClient,
|
||||
compressedBlobsQueue = compressedBlobsQueue,
|
||||
compressedBlobsQueueLimit = compressedBlobsQueueLimit
|
||||
compressedBlobsQueueLimit = compressedBlobsQueueLimit,
|
||||
)
|
||||
private val blobDecompressionTask = BlobDecompressionTask(
|
||||
vertx = vertx,
|
||||
@@ -101,7 +101,7 @@ class SubmissionsFetchingTask(
|
||||
blobDecompressor = blobDecompressor,
|
||||
rawBlobsQueue = compressedBlobsQueue,
|
||||
decompressedBlocksQueue = decompressedBlocksQueue,
|
||||
decompressedFinalizationQueueLimit = dynamicDecompressedBlobsQueueLimit::get
|
||||
decompressedFinalizationQueueLimit = dynamicDecompressedBlobsQueueLimit::get,
|
||||
)
|
||||
|
||||
@Synchronized
|
||||
@@ -109,7 +109,7 @@ class SubmissionsFetchingTask(
|
||||
return SafeFuture.allOf(
|
||||
submissionEventsFetchingTask.start(),
|
||||
blobFetchingTask.start(),
|
||||
blobDecompressionTask.start()
|
||||
blobDecompressionTask.start(),
|
||||
).thenCompose { super.start() }
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ class SubmissionsFetchingTask(
|
||||
return SafeFuture.allOf(
|
||||
submissionEventsFetchingTask.stop(),
|
||||
blobFetchingTask.stop(),
|
||||
blobDecompressionTask.stop()
|
||||
blobDecompressionTask.stop(),
|
||||
).thenCompose { super.stop() }
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ class SubmissionsFetchingTask(
|
||||
|
||||
@Synchronized
|
||||
fun pruneQueueForElementsUpToInclusive(
|
||||
elHeadBlockNumber: ULong
|
||||
elHeadBlockNumber: ULong,
|
||||
) {
|
||||
decompressedBlocksQueue.removeIf {
|
||||
it.submissionEvents.dataFinalizedEvent.event.endBlockNumber <= elHeadBlockNumber
|
||||
|
||||
@@ -29,7 +29,7 @@ class BlobDecompressorAndDeserializerV1Test {
|
||||
private val blockStaticFields = BlockHeaderStaticFields(
|
||||
coinbase = Address.ZERO.toArray(),
|
||||
gasLimit = 30_000_000UL,
|
||||
difficulty = 0UL
|
||||
difficulty = 0UL,
|
||||
)
|
||||
private lateinit var decompressorToDomain: BlobDecompressorAndDeserializer
|
||||
private lateinit var vertx: Vertx
|
||||
@@ -39,7 +39,7 @@ class BlobDecompressorAndDeserializerV1Test {
|
||||
vertx = Vertx.vertx()
|
||||
compressor = GoBackedBlobCompressor.getInstance(
|
||||
compressorVersion = BlobCompressorVersion.V1_2,
|
||||
dataLimit = 124 * 1024
|
||||
dataLimit = 124 * 1024,
|
||||
)
|
||||
val decompressor = GoNativeBlobDecompressorFactory.getInstance(BlobDecompressorVersion.V1_2_0)
|
||||
decompressorToDomain = BlobDecompressorToDomainV1(decompressor, blockStaticFields, vertx)
|
||||
@@ -57,7 +57,7 @@ class BlobDecompressorAndDeserializerV1Test {
|
||||
}
|
||||
|
||||
private fun assertBlockCompressionAndDecompression(
|
||||
blocksRLP: List<ByteArray>
|
||||
blocksRLP: List<ByteArray>,
|
||||
) {
|
||||
val blocks = blocksRLP.map(RLP::decodeBlockWithMainnetFunctions)
|
||||
val startingBlockNumber = blocks[0].header.number.toULong()
|
||||
@@ -66,7 +66,7 @@ class BlobDecompressorAndDeserializerV1Test {
|
||||
|
||||
val recoveredBlocks = decompressorToDomain.decompress(
|
||||
startBlockNumber = startingBlockNumber,
|
||||
blobs = blobs
|
||||
blobs = blobs,
|
||||
).get()
|
||||
assertThat(recoveredBlocks[0].header.blockNumber).isEqualTo(startingBlockNumber)
|
||||
|
||||
@@ -77,7 +77,7 @@ class BlobDecompressorAndDeserializerV1Test {
|
||||
|
||||
private fun assertBlockData(
|
||||
uncompressed: BlockFromL1RecoveredData,
|
||||
original: Block
|
||||
original: Block,
|
||||
) {
|
||||
try {
|
||||
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} " +
|
||||
"\n original =$original " +
|
||||
"\n uncompressed=$uncompressed ",
|
||||
e
|
||||
e,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun assertTransactionData(
|
||||
uncompressed: TransactionFromL1RecoveredData,
|
||||
original: Transaction
|
||||
original: Transaction,
|
||||
) {
|
||||
assertThat(uncompressed.type).isEqualTo(original.type.serializedType.toUByte())
|
||||
assertThat(uncompressed.from).isEqualTo(original.sender.toArray())
|
||||
|
||||
@@ -13,7 +13,7 @@ class StartingBlockCalculatorTest {
|
||||
lookbackFetchingIntervals(
|
||||
headBlockNumber = 50UL,
|
||||
recoveryStartBlockNumber = null,
|
||||
lookbackWindow = 10UL
|
||||
lookbackWindow = 10UL,
|
||||
).also { intervals ->
|
||||
assertThat(intervals.l1Interval).isNull()
|
||||
assertThat(intervals.elInterval).isEqualTo(BlockInterval(41UL, 50UL))
|
||||
@@ -23,7 +23,7 @@ class StartingBlockCalculatorTest {
|
||||
lookbackFetchingIntervals(
|
||||
headBlockNumber = 5UL,
|
||||
recoveryStartBlockNumber = null,
|
||||
lookbackWindow = 10UL
|
||||
lookbackWindow = 10UL,
|
||||
).also { intervals ->
|
||||
assertThat(intervals.l1Interval).isNull()
|
||||
assertThat(intervals.elInterval).isEqualTo(BlockInterval(0UL, 5UL))
|
||||
@@ -35,7 +35,7 @@ class StartingBlockCalculatorTest {
|
||||
lookbackFetchingIntervals(
|
||||
headBlockNumber = 50UL,
|
||||
recoveryStartBlockNumber = 51UL,
|
||||
lookbackWindow = 10UL
|
||||
lookbackWindow = 10UL,
|
||||
).also { intervals ->
|
||||
assertThat(intervals.l1Interval).isNull()
|
||||
assertThat(intervals.elInterval).isEqualTo(BlockInterval(41UL, 50UL))
|
||||
@@ -47,7 +47,7 @@ class StartingBlockCalculatorTest {
|
||||
lookbackFetchingIntervals(
|
||||
headBlockNumber = 0UL,
|
||||
recoveryStartBlockNumber = 1UL,
|
||||
lookbackWindow = 10UL
|
||||
lookbackWindow = 10UL,
|
||||
).also { intervals ->
|
||||
assertThat(intervals.l1Interval).isNull()
|
||||
assertThat(intervals.elInterval).isEqualTo(BlockInterval(0UL, 0UL))
|
||||
@@ -59,7 +59,7 @@ class StartingBlockCalculatorTest {
|
||||
lookbackFetchingIntervals(
|
||||
headBlockNumber = 50UL,
|
||||
recoveryStartBlockNumber = 10UL,
|
||||
lookbackWindow = 10UL
|
||||
lookbackWindow = 10UL,
|
||||
).also { intervals ->
|
||||
assertThat(intervals.l1Interval).isEqualTo(BlockInterval(41UL, 50UL))
|
||||
assertThat(intervals.elInterval).isNull()
|
||||
@@ -71,7 +71,7 @@ class StartingBlockCalculatorTest {
|
||||
lookbackFetchingIntervals(
|
||||
headBlockNumber = 50UL,
|
||||
recoveryStartBlockNumber = 45UL,
|
||||
lookbackWindow = 10UL
|
||||
lookbackWindow = 10UL,
|
||||
).also { intervals ->
|
||||
assertThat(intervals.l1Interval).isEqualTo(BlockInterval(45UL, 50UL))
|
||||
assertThat(intervals.elInterval).isEqualTo(BlockInterval(41UL, 44UL))
|
||||
@@ -86,7 +86,7 @@ class StartingBlockCalculatorTest {
|
||||
startBlockToFetchFromL1(
|
||||
headBlockNumber = 500UL,
|
||||
recoveryStartBlockNumber = null,
|
||||
lookbackWindow = 256UL
|
||||
lookbackWindow = 256UL,
|
||||
).also { result ->
|
||||
// Then
|
||||
assertThat(result).isEqualTo(501UL)
|
||||
@@ -95,7 +95,7 @@ class StartingBlockCalculatorTest {
|
||||
startBlockToFetchFromL1(
|
||||
headBlockNumber = 200UL,
|
||||
recoveryStartBlockNumber = null,
|
||||
lookbackWindow = 256UL
|
||||
lookbackWindow = 256UL,
|
||||
).also { result ->
|
||||
// Then
|
||||
assertThat(result).isEqualTo(201UL)
|
||||
@@ -107,7 +107,7 @@ class StartingBlockCalculatorTest {
|
||||
startBlockToFetchFromL1(
|
||||
headBlockNumber = 500UL,
|
||||
recoveryStartBlockNumber = 250UL,
|
||||
lookbackWindow = 100UL
|
||||
lookbackWindow = 100UL,
|
||||
).also { result ->
|
||||
// Then
|
||||
assertThat(result).isEqualTo(400UL)
|
||||
@@ -119,7 +119,7 @@ class StartingBlockCalculatorTest {
|
||||
startBlockToFetchFromL1(
|
||||
headBlockNumber = 500UL,
|
||||
recoveryStartBlockNumber = 450UL,
|
||||
lookbackWindow = 100UL
|
||||
lookbackWindow = 100UL,
|
||||
).also { result ->
|
||||
// Then
|
||||
assertThat(result).isEqualTo(450UL)
|
||||
@@ -129,7 +129,7 @@ class StartingBlockCalculatorTest {
|
||||
startBlockToFetchFromL1(
|
||||
headBlockNumber = 50UL,
|
||||
recoveryStartBlockNumber = 45UL,
|
||||
lookbackWindow = 100UL
|
||||
lookbackWindow = 100UL,
|
||||
).also { result ->
|
||||
// Then
|
||||
assertThat(result).isEqualTo(45UL)
|
||||
|
||||
@@ -21,7 +21,7 @@ class ExecutionLayerInProcessClient(
|
||||
private val blockchainService: BlockchainService,
|
||||
private val stateRecoveryModeManager: RecoveryModeManager,
|
||||
private val stateRecoveryStatusPersistence: RecoveryStatusPersistence,
|
||||
private val blockImporter: BlockImporter
|
||||
private val blockImporter: BlockImporter,
|
||||
) : ExecutionLayerClient {
|
||||
companion object {
|
||||
fun create(
|
||||
@@ -29,7 +29,7 @@ class ExecutionLayerInProcessClient(
|
||||
simulatorService: BlockSimulationService,
|
||||
synchronizationService: SynchronizationService,
|
||||
stateRecoveryModeManager: RecoveryModeManager,
|
||||
stateRecoveryStatusPersistence: RecoveryStatusPersistence
|
||||
stateRecoveryStatusPersistence: RecoveryStatusPersistence,
|
||||
): ExecutionLayerInProcessClient {
|
||||
return ExecutionLayerInProcessClient(
|
||||
blockchainService = blockchainService,
|
||||
@@ -38,8 +38,8 @@ class ExecutionLayerInProcessClient(
|
||||
blockImporter = BlockImporter(
|
||||
blockchainService = blockchainService,
|
||||
simulatorService = simulatorService,
|
||||
synchronizationService = synchronizationService
|
||||
)
|
||||
synchronizationService = synchronizationService,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -71,8 +71,8 @@ class ExecutionLayerInProcessClient(
|
||||
SafeFuture.completedFuture(
|
||||
BlockNumberAndHash(
|
||||
it.number.toULong(),
|
||||
it.blockHash.toArray()
|
||||
)
|
||||
it.blockHash.toArray(),
|
||||
),
|
||||
)
|
||||
}
|
||||
?: SafeFuture.failedFuture(IllegalArgumentException("Block not found for parameter: $blockParameter"))
|
||||
@@ -91,8 +91,8 @@ class ExecutionLayerInProcessClient(
|
||||
.completedFuture(
|
||||
StateRecoveryStatus(
|
||||
headBlockNumber = stateRecoveryModeManager.headBlockNumber,
|
||||
stateRecoverStartBlockNumber = stateRecoveryModeManager.targetBlockNumber
|
||||
)
|
||||
stateRecoverStartBlockNumber = stateRecoveryModeManager.targetBlockNumber,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -102,8 +102,8 @@ class ExecutionLayerInProcessClient(
|
||||
return SafeFuture.completedFuture(
|
||||
StateRecoveryStatus(
|
||||
headBlockNumber = stateRecoveryModeManager.headBlockNumber,
|
||||
stateRecoverStartBlockNumber = stateRecoveryStatusPersistence.getRecoveryStartBlockNumber()
|
||||
)
|
||||
stateRecoverStartBlockNumber = stateRecoveryStatusPersistence.getRecoveryStartBlockNumber(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ class ExecutionLayerInProcessClient(
|
||||
} else {
|
||||
log.debug(
|
||||
"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),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ fun createAppAllInProcess(
|
||||
blobScanRequestRetryConfig: RetryConfig,
|
||||
blobscanRequestRatelimitBackoffDelay: Duration?,
|
||||
blockHeaderStaticFields: BlockHeaderStaticFields,
|
||||
appConfig: StateRecoveryApp.Config
|
||||
appConfig: StateRecoveryApp.Config,
|
||||
): StateRecoveryApp {
|
||||
return createAppClients(
|
||||
vertx = vertx,
|
||||
@@ -49,7 +49,7 @@ fun createAppAllInProcess(
|
||||
l1RequestRetryConfig = l1RequestRetryConfig,
|
||||
blobScanEndpoint = blobScanEndpoint,
|
||||
blobScanRequestRetryConfig = blobScanRequestRetryConfig,
|
||||
blobscanRequestRateLimitBackoffDelay = blobscanRequestRatelimitBackoffDelay
|
||||
blobscanRequestRateLimitBackoffDelay = blobscanRequestRatelimitBackoffDelay,
|
||||
).let { clients ->
|
||||
val app = StateRecoveryApp(
|
||||
vertx = vertx,
|
||||
@@ -60,7 +60,7 @@ fun createAppAllInProcess(
|
||||
stateManagerClient = clients.stateManagerClient,
|
||||
transactionDetailsClient = clients.transactionDetailsClient,
|
||||
blockHeaderStaticFields = blockHeaderStaticFields,
|
||||
config = appConfig
|
||||
config = appConfig,
|
||||
)
|
||||
app
|
||||
}
|
||||
@@ -71,7 +71,7 @@ data class AppClients(
|
||||
val ethLogsSearcher: EthLogsSearcherImpl,
|
||||
val blobScanClient: BlobScanClient,
|
||||
val stateManagerClient: StateManagerClientV1,
|
||||
val transactionDetailsClient: TransactionDetailsClient
|
||||
val transactionDetailsClient: TransactionDetailsClient,
|
||||
)
|
||||
|
||||
fun RetryConfig.toRequestRetryConfig(): RequestRetryConfig {
|
||||
@@ -79,7 +79,7 @@ fun RetryConfig.toRequestRetryConfig(): RequestRetryConfig {
|
||||
maxRetries = this.maxRetries,
|
||||
timeout = this.timeout,
|
||||
backoffDelay = this.backoffDelay,
|
||||
failuresWarningThreshold = this.failuresWarningThreshold
|
||||
failuresWarningThreshold = this.failuresWarningThreshold,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -95,14 +95,14 @@ fun createAppClients(
|
||||
stateManagerClientEndpoint: URI,
|
||||
blobscanRequestRateLimitBackoffDelay: Duration? = null,
|
||||
stateManagerRequestRetry: RetryConfig = RetryConfig(backoffDelay = 1.seconds),
|
||||
zkStateManagerVersion: String = "2.3.0"
|
||||
zkStateManagerVersion: String = "2.3.0",
|
||||
): AppClients {
|
||||
val lineaContractClient = Web3JLineaRollupSmartContractClientReadOnly(
|
||||
contractAddress = smartContractAddress,
|
||||
web3j = createWeb3jHttpClient(
|
||||
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 log = LogManager.getLogger("linea.plugin.staterecovery.clients.l1.logs-searcher")
|
||||
@@ -110,15 +110,15 @@ fun createAppClients(
|
||||
vertx = vertx,
|
||||
rpcUrl = l1RpcEndpoint.toString(),
|
||||
requestRetryConfig = l1RequestRetryConfig,
|
||||
log = log
|
||||
log = log,
|
||||
)
|
||||
EthLogsSearcherImpl(
|
||||
vertx = vertx,
|
||||
ethApiClient = web3jEthApiClient,
|
||||
config = EthLogsSearcherImpl.Config(
|
||||
loopSuccessBackoffDelay = l1SuccessBackoffDelay
|
||||
loopSuccessBackoffDelay = l1SuccessBackoffDelay,
|
||||
),
|
||||
log = log
|
||||
log = log,
|
||||
)
|
||||
}
|
||||
val blobScanClient = BlobScanClient.create(
|
||||
@@ -126,7 +126,7 @@ fun createAppClients(
|
||||
endpoint = blobScanEndpoint,
|
||||
requestRetryConfig = blobScanRequestRetryConfig,
|
||||
logger = LogManager.getLogger("linea.plugin.staterecovery.clients.l1.blob-scan"),
|
||||
rateLimitBackoffDelay = blobscanRequestRateLimitBackoffDelay
|
||||
rateLimitBackoffDelay = blobscanRequestRateLimitBackoffDelay,
|
||||
)
|
||||
val jsonRpcClientFactory = VertxHttpJsonRpcClientFactory(vertx, MicrometerMetricsFacade(meterRegistry))
|
||||
val stateManagerClient: StateManagerClientV1 = StateManagerV1JsonRpcClient.create(
|
||||
@@ -135,19 +135,19 @@ fun createAppClients(
|
||||
maxInflightRequestsPerClient = 10u,
|
||||
requestRetry = stateManagerRequestRetry.toRequestRetryConfig(),
|
||||
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(
|
||||
jsonRpcClientFactory = jsonRpcClientFactory,
|
||||
endpoint = l1RpcEndpoint,
|
||||
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(
|
||||
lineaContractClient = lineaContractClient,
|
||||
ethLogsSearcher = ethLogsSearcher,
|
||||
blobScanClient = blobScanClient,
|
||||
stateManagerClient = stateManagerClient,
|
||||
transactionDetailsClient = transactionDetailsClient
|
||||
transactionDetailsClient = transactionDetailsClient,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import org.hyperledger.besu.plugin.data.BlockHeader
|
||||
|
||||
data class BlockContextData(
|
||||
private val blockHeader: BlockHeader,
|
||||
private val blockBody: BlockBody
|
||||
private val blockBody: BlockBody,
|
||||
) : BlockContext {
|
||||
override fun getBlockHeader(): BlockHeader = blockHeader
|
||||
override fun getBlockBody(): BlockBody = blockBody
|
||||
|
||||
@@ -13,7 +13,7 @@ import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
class BlockHashLookupWithRecoverySupport(
|
||||
val lookbackWindow: ULong,
|
||||
private val log: Logger = LogManager.getLogger(BlockHashLookupWithRecoverySupport::class.java)
|
||||
private val log: Logger = LogManager.getLogger(BlockHashLookupWithRecoverySupport::class.java),
|
||||
) : BlockHashLookup {
|
||||
private val lookbackHashesMap = ConcurrentHashMap<ULong, ByteArray>()
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ class BlockImporter(
|
||||
private val simulatorService: BlockSimulationService,
|
||||
private val synchronizationService: SynchronizationService,
|
||||
private val blockHashLookup: BlockHashLookupWithRecoverySupport = BlockHashLookupWithRecoverySupport(
|
||||
lookbackWindow = 256UL
|
||||
)
|
||||
lookbackWindow = 256UL,
|
||||
),
|
||||
) {
|
||||
private val log = LogManager.getLogger(BlockImporter::class.java)
|
||||
private val chainId = blockchainService.chainId.orElseThrow().toULong()
|
||||
@@ -40,16 +40,16 @@ class BlockImporter(
|
||||
}
|
||||
|
||||
private fun executeBlockWithTransactionsWithoutSignature(
|
||||
block: BlockFromL1RecoveredData
|
||||
block: BlockFromL1RecoveredData,
|
||||
): PluginBlockSimulationResult {
|
||||
log.trace(
|
||||
"simulating import block={} blockHash={}",
|
||||
block.header.blockNumber,
|
||||
block.header.blockHash.encodeHex()
|
||||
block.header.blockHash.encodeHex(),
|
||||
)
|
||||
val transactions = TransactionMapper.mapToBesu(
|
||||
block.transactions,
|
||||
chainId
|
||||
chainId,
|
||||
)
|
||||
val parentBlockNumber = block.header.blockNumber.toLong() - 1
|
||||
|
||||
@@ -58,13 +58,13 @@ class BlockImporter(
|
||||
parentBlockNumber,
|
||||
transactions,
|
||||
createOverrides(block, blockHashLookup::getHash),
|
||||
StateOverrideMap()
|
||||
StateOverrideMap(),
|
||||
)
|
||||
|
||||
log.trace(
|
||||
" import simulation result: block={} blockHeader={}",
|
||||
executedBlockResult.blockHeader.number,
|
||||
executedBlockResult.blockHeader
|
||||
executedBlockResult.blockHeader,
|
||||
)
|
||||
return executedBlockResult
|
||||
}
|
||||
@@ -73,7 +73,7 @@ class BlockImporter(
|
||||
log.trace(
|
||||
"calling simulateAndPersistWorldState block={} blockHeader={}",
|
||||
context.blockHeader.number,
|
||||
context.blockHeader
|
||||
context.blockHeader,
|
||||
)
|
||||
val parentBlockNumber = context.blockHeader.number - 1
|
||||
val importedBlockResult =
|
||||
@@ -81,12 +81,12 @@ class BlockImporter(
|
||||
parentBlockNumber,
|
||||
context.blockBody.transactions,
|
||||
createOverrides(context.blockHeader, blockHashLookup::getHash),
|
||||
StateOverrideMap()
|
||||
StateOverrideMap(),
|
||||
)
|
||||
log.trace(
|
||||
"simulateAndPersistWorldState result: block={} blockHeader={}",
|
||||
context.blockHeader.number,
|
||||
importedBlockResult.blockHeader
|
||||
importedBlockResult.blockHeader,
|
||||
)
|
||||
storeAndSetHead(importedBlockResult)
|
||||
return importedBlockResult
|
||||
@@ -95,12 +95,12 @@ class BlockImporter(
|
||||
private fun storeAndSetHead(block: PluginBlockSimulationResult) {
|
||||
log.debug(
|
||||
"storeAndSetHead result: blockHeader={}",
|
||||
block.blockHeader
|
||||
block.blockHeader,
|
||||
)
|
||||
blockchainService.storeBlock(
|
||||
block.blockHeader,
|
||||
block.blockBody,
|
||||
block.receipts
|
||||
block.receipts,
|
||||
)
|
||||
synchronizationService.setHeadUnsafe(block.blockHeader, block.blockBody)
|
||||
}
|
||||
@@ -108,7 +108,7 @@ class BlockImporter(
|
||||
companion object {
|
||||
fun createOverrides(
|
||||
blockFromBlob: BlockFromL1RecoveredData,
|
||||
blockHashLookup: (Long) -> Hash
|
||||
blockHashLookup: (Long) -> Hash,
|
||||
): BlockOverrides {
|
||||
return BlockOverrides.builder()
|
||||
.blockHash(Hash.wrap(Bytes32.wrap(blockFromBlob.header.blockHash)))
|
||||
@@ -124,7 +124,7 @@ class BlockImporter(
|
||||
|
||||
fun createOverrides(
|
||||
blockHeader: BlockHeader,
|
||||
blockHashLookup: (Long) -> Hash
|
||||
blockHashLookup: (Long) -> Hash,
|
||||
): BlockOverrides {
|
||||
return BlockOverrides.builder()
|
||||
.feeRecipient(blockHeader.coinbase)
|
||||
|
||||
@@ -36,7 +36,7 @@ open class LineaStateRecoveryPlugin : BesuPlugin {
|
||||
warningExceptionTime = 5.minutes,
|
||||
jvmMetricsEnabled = false,
|
||||
prometheusMetricsEnabled = false,
|
||||
preferNativeTransport = false
|
||||
preferNativeTransport = false,
|
||||
)
|
||||
private val cliOptions = PluginCliOptions()
|
||||
private lateinit var serviceManager: ServiceManager
|
||||
@@ -59,18 +59,18 @@ open class LineaStateRecoveryPlugin : BesuPlugin {
|
||||
val blockHeaderStaticFields = BlockHeaderStaticFields(
|
||||
coinbase = config.lineaSequencerBeneficiaryAddress.toArray(),
|
||||
gasLimit = config.lineaBlockGasLimit,
|
||||
difficulty = config.lineaBlockDifficulty
|
||||
difficulty = config.lineaBlockDifficulty,
|
||||
)
|
||||
this.recoveryStatusPersistence = FileBasedRecoveryStatusPersistence(
|
||||
serviceManager.getServiceOrThrow(BesuConfiguration::class.java)
|
||||
.dataPath
|
||||
.resolve("plugin-staterecovery-status.json")
|
||||
.resolve("plugin-staterecovery-status.json"),
|
||||
)
|
||||
log.info(
|
||||
"starting: config={} blockHeaderStaticFields={} previousRecoveryStartBlockNumber={}",
|
||||
config,
|
||||
blockHeaderStaticFields,
|
||||
this.recoveryStatusPersistence.getRecoveryStartBlockNumber()
|
||||
this.recoveryStatusPersistence.getRecoveryStartBlockNumber(),
|
||||
)
|
||||
|
||||
val synchronizationService = serviceManager.getServiceOrThrow(SynchronizationService::class.java)
|
||||
@@ -80,7 +80,7 @@ open class LineaStateRecoveryPlugin : BesuPlugin {
|
||||
recoveryStatePersistence = this.recoveryStatusPersistence,
|
||||
synchronizationService = synchronizationService,
|
||||
headBlockNumber = blockchainService.chainHeadHeader.number.toULong(),
|
||||
debugForceSyncStopBlockNumber = config.debugForceSyncStopBlockNumber
|
||||
debugForceSyncStopBlockNumber = config.debugForceSyncStopBlockNumber,
|
||||
)
|
||||
val simulatorService = serviceManager.getServiceOrThrow(BlockSimulationService::class.java)
|
||||
val executionLayerClient = ExecutionLayerInProcessClient.create(
|
||||
@@ -88,7 +88,7 @@ open class LineaStateRecoveryPlugin : BesuPlugin {
|
||||
stateRecoveryModeManager = this.recoveryModeManager,
|
||||
stateRecoveryStatusPersistence = this.recoveryStatusPersistence,
|
||||
simulatorService = simulatorService,
|
||||
synchronizationService = synchronizationService
|
||||
synchronizationService = synchronizationService,
|
||||
)
|
||||
|
||||
this.stateRecoverApp = run {
|
||||
@@ -112,8 +112,8 @@ open class LineaStateRecoveryPlugin : BesuPlugin {
|
||||
l1LatestSearchBlock = config.l1HighestSearchBlock,
|
||||
l1PollingInterval = config.l1PollingInterval,
|
||||
overridingRecoveryStartBlockNumber = config.overridingRecoveryStartBlockNumber,
|
||||
debugForceSyncStopBlockNumber = config.debugForceSyncStopBlockNumber
|
||||
)
|
||||
debugForceSyncStopBlockNumber = config.debugForceSyncStopBlockNumber,
|
||||
),
|
||||
)
|
||||
}
|
||||
// add recoverty mode manager as listener to block added events
|
||||
@@ -129,7 +129,7 @@ open class LineaStateRecoveryPlugin : BesuPlugin {
|
||||
this.recoveryModeManager.enableRecoveryModeIfNecessary()
|
||||
log.info(
|
||||
"started: recoveryStartBlockNumber={}",
|
||||
this.recoveryStatusPersistence.getRecoveryStartBlockNumber()
|
||||
this.recoveryStatusPersistence.getRecoveryStartBlockNumber(),
|
||||
)
|
||||
this.stateRecoverApp.start().get()
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ data class PluginConfig(
|
||||
val blobscanRequestRatelimitBackoffDelay: kotlin.time.Duration?,
|
||||
val shomeiEndpoint: URI,
|
||||
val overridingRecoveryStartBlockNumber: ULong? = null,
|
||||
val debugForceSyncStopBlockNumber: ULong? = null
|
||||
val debugForceSyncStopBlockNumber: ULong? = null,
|
||||
) {
|
||||
init {
|
||||
require(l1PollingInterval >= 1.milliseconds) { "Polling interval=$l1PollingInterval must be greater than 1ms." }
|
||||
@@ -43,7 +43,7 @@ class PluginCliOptions {
|
||||
description = ["Linea sequencer beneficiary address"],
|
||||
required = true,
|
||||
converter = [AddressConverter::class],
|
||||
defaultValue = "\${env:LINEA_SEQUENCER_BENEFICIARY_ADDRESS}"
|
||||
defaultValue = "\${env:LINEA_SEQUENCER_BENEFICIARY_ADDRESS}",
|
||||
)
|
||||
lateinit var lineaSequencerBeneficiaryAddress: Address
|
||||
|
||||
@@ -51,7 +51,7 @@ class PluginCliOptions {
|
||||
names = ["--$cliOptionsPrefix-linea-block-gas-limit"],
|
||||
description = ["Linea Block gas limit. Default 2B (2_000_000_000)"],
|
||||
required = false,
|
||||
defaultValue = "\${env:LINEA_BLOCK_GAS_LIMIT}"
|
||||
defaultValue = "\${env:LINEA_BLOCK_GAS_LIMIT}",
|
||||
)
|
||||
var lineaBlockGasLimit: Long = 2_000_000_000L
|
||||
|
||||
@@ -59,7 +59,7 @@ class PluginCliOptions {
|
||||
names = ["--$cliOptionsPrefix-linea-block-difficulty"],
|
||||
description = ["Linea Block difficulty. Default 2"],
|
||||
required = false,
|
||||
defaultValue = "\${env:LINEA_BLOCK_DIFFICULTY}"
|
||||
defaultValue = "\${env:LINEA_BLOCK_DIFFICULTY}",
|
||||
)
|
||||
var lineaBlockDifficulty: Long = 2
|
||||
|
||||
@@ -68,14 +68,14 @@ class PluginCliOptions {
|
||||
description = ["L1 smart contract address"],
|
||||
required = true,
|
||||
converter = [AddressConverter::class],
|
||||
defaultValue = "\${env:L1_ROLLUP_CONTRACT_ADDRESS}"
|
||||
defaultValue = "\${env:L1_ROLLUP_CONTRACT_ADDRESS}",
|
||||
)
|
||||
lateinit var l1SmartContractAddress: Address
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--$cliOptionsPrefix-l1-endpoint"],
|
||||
description = ["L1 RPC endpoint"],
|
||||
required = true
|
||||
required = true,
|
||||
)
|
||||
lateinit var l1RpcEndpoint: URI
|
||||
|
||||
@@ -83,7 +83,7 @@ class PluginCliOptions {
|
||||
names = ["--$cliOptionsPrefix-l1-polling-interval"],
|
||||
defaultValue = "PT12S",
|
||||
description = ["L1 polling interval for new finalized blobs"],
|
||||
required = false
|
||||
required = false,
|
||||
)
|
||||
var l1PollingInterval: java.time.Duration = java.time.Duration.ofSeconds(12)
|
||||
|
||||
@@ -91,7 +91,7 @@ class PluginCliOptions {
|
||||
names = ["--$cliOptionsPrefix-l1-get-logs-chunk-size"],
|
||||
defaultValue = "10000",
|
||||
description = ["Chuck size (fromBlock..toBlock) for eth_getLogs initial search loop"],
|
||||
required = false
|
||||
required = false,
|
||||
)
|
||||
var l1GetLogsChunkSize: Int = 10_000
|
||||
|
||||
@@ -100,10 +100,10 @@ class PluginCliOptions {
|
||||
defaultValue = "EARLIEST",
|
||||
description = [
|
||||
"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],
|
||||
required = false
|
||||
required = false,
|
||||
)
|
||||
var l1EarliestSearchBlock: BlockParameter = BlockParameter.Tag.EARLIEST
|
||||
|
||||
@@ -112,10 +112,10 @@ class PluginCliOptions {
|
||||
defaultValue = "FINALIZED",
|
||||
description = [
|
||||
"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],
|
||||
required = false
|
||||
required = false,
|
||||
)
|
||||
var l1HighestSearchBlock: BlockParameter = BlockParameter.Tag.FINALIZED
|
||||
|
||||
@@ -123,9 +123,9 @@ class PluginCliOptions {
|
||||
names = ["--$cliOptionsPrefix-l1-success-backoff-delay"],
|
||||
description = [
|
||||
"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
|
||||
|
||||
@@ -133,7 +133,7 @@ class PluginCliOptions {
|
||||
names = ["--$cliOptionsPrefix-l1-retry-backoff-delay"],
|
||||
defaultValue = "PT1S",
|
||||
description = ["L1 RPC api retry backoff delay, default 1s"],
|
||||
required = false
|
||||
required = false,
|
||||
)
|
||||
var l1RequestRetryBackoffDelay: java.time.Duration = java.time.Duration.ofSeconds(1)
|
||||
|
||||
@@ -141,9 +141,9 @@ class PluginCliOptions {
|
||||
names = ["--$cliOptionsPrefix-l1-retry-timeout"],
|
||||
description = [
|
||||
"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
|
||||
|
||||
@@ -151,37 +151,37 @@ class PluginCliOptions {
|
||||
names = ["--$cliOptionsPrefix-l1-retry-limit"],
|
||||
description = [
|
||||
"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
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--$cliOptionsPrefix-shomei-endpoint"],
|
||||
description = ["shomei (state manager) endpoint"],
|
||||
required = true
|
||||
required = true,
|
||||
)
|
||||
lateinit var shomeiEndpoint: URI
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--$cliOptionsPrefix-blobscan-endpoint"],
|
||||
description = ["blobscan api endpoint"],
|
||||
required = true
|
||||
required = true,
|
||||
)
|
||||
lateinit var blobscanEndpoint: URI
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--$cliOptionsPrefix-blobscan-retry-backoff-delay"],
|
||||
description = ["blobscan api retry backoff delay, default 1s"],
|
||||
required = false
|
||||
required = false,
|
||||
)
|
||||
var blobscanRequestRetryBackoffDelay: java.time.Duration = java.time.Duration.ofSeconds(1)
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--$cliOptionsPrefix-blobscan-ratelimit-backoff-delay"],
|
||||
description = ["blobscan api retry ratelimit backoff delay, default is disabled"],
|
||||
required = false
|
||||
required = false,
|
||||
)
|
||||
var blobscanRequestRatelimitBackoffDelay: java.time.Duration? = null
|
||||
|
||||
@@ -189,9 +189,9 @@ class PluginCliOptions {
|
||||
names = ["--$cliOptionsPrefix-blobscan-retry-timeout"],
|
||||
description = [
|
||||
"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
|
||||
|
||||
@@ -199,9 +199,9 @@ class PluginCliOptions {
|
||||
names = ["--$cliOptionsPrefix-blobscan-retry-limit"],
|
||||
description = [
|
||||
"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
|
||||
|
||||
@@ -209,10 +209,10 @@ class PluginCliOptions {
|
||||
names = ["--$cliOptionsPrefix-overriding-recovery-start-block-number"],
|
||||
description = [
|
||||
"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}",
|
||||
required = false
|
||||
required = false,
|
||||
)
|
||||
var overridingRecoveryStartBlockNumber: Long? = null
|
||||
|
||||
@@ -220,10 +220,10 @@ class PluginCliOptions {
|
||||
names = ["--$cliOptionsPrefix-debug-force-sync-stop-block-number"],
|
||||
description = [
|
||||
"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}",
|
||||
required = false
|
||||
required = false,
|
||||
)
|
||||
var debugForceSyncStopBlockNumber: Long? = null
|
||||
|
||||
@@ -252,25 +252,25 @@ class PluginCliOptions {
|
||||
l1RequestRetryConfig = RetryConfig(
|
||||
backoffDelay = l1RequestRetryBackoffDelay.toKotlinDuration(),
|
||||
timeout = l1RequestRetryTimeout?.toKotlinDuration(),
|
||||
maxRetries = l1RequestRetryLimit?.toUInt()
|
||||
maxRetries = l1RequestRetryLimit?.toUInt(),
|
||||
),
|
||||
blobscanEndpoint = blobscanEndpoint,
|
||||
blobScanRequestRetryConfig = RetryConfig(
|
||||
backoffDelay = blobscanRequestRetryBackoffDelay.toKotlinDuration(),
|
||||
timeout = blobscanRequestRetryTimeout?.toKotlinDuration(),
|
||||
maxRetries = blobscanRequestRetryLimit?.toUInt()
|
||||
maxRetries = blobscanRequestRetryLimit?.toUInt(),
|
||||
),
|
||||
blobscanRequestRatelimitBackoffDelay = blobscanRequestRatelimitBackoffDelay?.toKotlinDuration(),
|
||||
shomeiEndpoint = shomeiEndpoint,
|
||||
overridingRecoveryStartBlockNumber = overridingRecoveryStartBlockNumber?.toULong(),
|
||||
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber?.toULong()
|
||||
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber?.toULong(),
|
||||
)
|
||||
}
|
||||
|
||||
class AddressConverter : CommandLine.ITypeConverter<Address> {
|
||||
override fun convert(value: String): Address {
|
||||
return Address.fromHexStringStrict(value) ?: throw CommandLine.TypeConversionException(
|
||||
"Invalid address: $value"
|
||||
"Invalid address: $value",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ class RecoveryModeManager(
|
||||
private val miningService: MiningService,
|
||||
private val recoveryStatePersistence: RecoveryStatusPersistence,
|
||||
private val debugForceSyncStopBlockNumber: ULong? = null,
|
||||
headBlockNumber: ULong
|
||||
headBlockNumber: ULong,
|
||||
) :
|
||||
BesuEvents.BlockAddedListener {
|
||||
private val log: Logger = LogManager.getLogger(RecoveryModeManager::class.java.name)
|
||||
@@ -37,7 +37,7 @@ class RecoveryModeManager(
|
||||
log.info(
|
||||
"enabling recovery mode immediately at blockNumber={} recoveryTargetBlockNumber={}",
|
||||
headBlockNumber,
|
||||
targetBlockNumber
|
||||
targetBlockNumber,
|
||||
)
|
||||
switchToRecoveryMode()
|
||||
}
|
||||
@@ -56,14 +56,14 @@ class RecoveryModeManager(
|
||||
log.info(
|
||||
"Stopping synchronization services at block={} recoveryTargetBlockNumber={} was reached",
|
||||
headBlockNumber,
|
||||
targetBlockNumber
|
||||
targetBlockNumber,
|
||||
)
|
||||
switchToRecoveryMode()
|
||||
} else if (debugForceSyncStopBlockNumber != null && headBlockNumber >= debugForceSyncStopBlockNumber) {
|
||||
log.info(
|
||||
"Stopping synchronization services at block={} debugForceSyncStopBlockNumber={}",
|
||||
headBlockNumber,
|
||||
debugForceSyncStopBlockNumber
|
||||
debugForceSyncStopBlockNumber,
|
||||
)
|
||||
stopBesuServices()
|
||||
}
|
||||
@@ -71,7 +71,7 @@ class RecoveryModeManager(
|
||||
|
||||
private fun hasReachedTargetBlock(
|
||||
headBlockNumber: ULong = this.headBlockNumber,
|
||||
targetBlockNumber: ULong? = this.targetBlockNumber
|
||||
targetBlockNumber: ULong? = this.targetBlockNumber,
|
||||
): Boolean {
|
||||
return (headBlockNumber + 1u) >= (targetBlockNumber ?: ULong.MAX_VALUE)
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ object TransactionMapper {
|
||||
*/
|
||||
fun mapToBesu(
|
||||
transaction: TransactionFromL1RecoveredData,
|
||||
chainId: ULong
|
||||
chainId: ULong,
|
||||
): Transaction {
|
||||
val builder = Transaction.builder()
|
||||
builder
|
||||
@@ -48,13 +48,13 @@ object TransactionMapper {
|
||||
}
|
||||
|
||||
private fun mapAccessListEntries(
|
||||
accessList: List<AccessTuple>?
|
||||
accessList: List<AccessTuple>?,
|
||||
): List<AccessListEntry>? {
|
||||
return accessList
|
||||
?.map { accessTupleParameter ->
|
||||
AccessListEntry.createAccessListEntry(
|
||||
accessTupleParameter.address.toBesuAddress(),
|
||||
accessTupleParameter.storageKeys.map { it.encodeHex() }
|
||||
accessTupleParameter.storageKeys.map { it.encodeHex() },
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ object TransactionMapper {
|
||||
*/
|
||||
fun mapToBesu(
|
||||
transactions: List<TransactionFromL1RecoveredData>,
|
||||
defaultChainId: ULong
|
||||
defaultChainId: ULong,
|
||||
): List<Transaction> {
|
||||
return transactions.map { tx -> mapToBesu(tx, defaultChainId) }
|
||||
}
|
||||
|
||||
@@ -15,16 +15,16 @@ class BlockHashLookupWithRecoverySupportTest {
|
||||
lookback.addLookbackHashes(
|
||||
mapOf(
|
||||
1UL to hashOf(1UL),
|
||||
2UL to hashOf(3UL)
|
||||
)
|
||||
2UL to hashOf(3UL),
|
||||
),
|
||||
)
|
||||
|
||||
assertThatThrownBy {
|
||||
lookback.addLookbackHashes(
|
||||
mapOf(
|
||||
1UL to hashOf(1UL),
|
||||
3UL to hashOf(3UL)
|
||||
)
|
||||
3UL to hashOf(3UL),
|
||||
),
|
||||
)
|
||||
}
|
||||
.isInstanceOf(IllegalArgumentException::class.java)
|
||||
@@ -34,7 +34,7 @@ class BlockHashLookupWithRecoverySupportTest {
|
||||
@Test
|
||||
fun `addHeadBlockHash should update and prune the lookback hashes outside the lookback window`() {
|
||||
val lookback = BlockHashLookupWithRecoverySupport(
|
||||
lookbackWindow = 3UL
|
||||
lookbackWindow = 3UL,
|
||||
)
|
||||
|
||||
lookback.addHeadBlockHash(0UL, hashOf(123UL))
|
||||
|
||||
@@ -24,11 +24,11 @@ class StaticVertxHttpRequestRateLimiter(
|
||||
.div(5)
|
||||
.coerceAtLeast(1.milliseconds),
|
||||
private val requestLogFormatter: VertxHttpLoggingFormatter,
|
||||
private val logger: Logger = LogManager.getLogger(StaticVertxHttpRequestRateLimiter::class.java)
|
||||
private val logger: Logger = LogManager.getLogger(StaticVertxHttpRequestRateLimiter::class.java),
|
||||
) : VertxHttpRequestSender {
|
||||
private data class RequestAndFutureResponse(
|
||||
val request: HttpRequest<Buffer>,
|
||||
val future: SafeFuture<HttpResponse<Buffer>>
|
||||
val future: SafeFuture<HttpResponse<Buffer>>,
|
||||
)
|
||||
|
||||
private val rateLimitPerSecond = 1.seconds.div(rateLimitBackoffDelay).toInt()
|
||||
@@ -54,7 +54,7 @@ class StaticVertxHttpRequestRateLimiter(
|
||||
rateLimitPerSecond,
|
||||
requestQueue.size,
|
||||
rateLimitBackoffDelay - elapsedTimeSinceLastRequest,
|
||||
requestLogFormatter.toLogString(requestQueue.peek().request)
|
||||
requestLogFormatter.toLogString(requestQueue.peek().request),
|
||||
)
|
||||
return
|
||||
}
|
||||
@@ -93,7 +93,7 @@ class StaticVertxHttpRequestRateLimiter(
|
||||
rateLimitPerSecond,
|
||||
requestQueue.size,
|
||||
rateLimitBackoffDelay - lastRequestFiredTime.elapsedNow(),
|
||||
requestLogFormatter.toLogString(request)
|
||||
requestLogFormatter.toLogString(request),
|
||||
)
|
||||
|
||||
requestQueue.add(req)
|
||||
|
||||
@@ -9,7 +9,7 @@ interface VertxHttpLoggingFormatter {
|
||||
fun toLogString(
|
||||
request: HttpRequest<Buffer>,
|
||||
response: HttpResponse<Buffer>? = null,
|
||||
failureCause: Throwable? = null
|
||||
failureCause: Throwable? = null,
|
||||
): String
|
||||
}
|
||||
|
||||
@@ -22,14 +22,14 @@ fun HttpRequest<*>.fullUri(): String {
|
||||
scheme,
|
||||
this.host(),
|
||||
this.port(),
|
||||
path
|
||||
path,
|
||||
)
|
||||
}
|
||||
|
||||
class VertxRestLoggingFormatter(
|
||||
private val includeFullUri: Boolean = false,
|
||||
private val uriTransformer: (String) -> String = { it },
|
||||
private val responseLogMaxSize: UInt? = null
|
||||
private val responseLogMaxSize: UInt? = null,
|
||||
) : VertxHttpLoggingFormatter {
|
||||
fun HttpRequest<*>.uriToLog(): String {
|
||||
return if (includeFullUri) {
|
||||
@@ -46,14 +46,14 @@ class VertxRestLoggingFormatter(
|
||||
override fun toLogString(
|
||||
request: HttpRequest<Buffer>,
|
||||
response: HttpResponse<Buffer>?,
|
||||
failureCause: Throwable?
|
||||
failureCause: Throwable?,
|
||||
): String {
|
||||
return if (failureCause != null) {
|
||||
String.format(
|
||||
"<-- %s %s %s",
|
||||
request.method(),
|
||||
uriTransformer.invoke(request.uriToLog()),
|
||||
failureCause.message?.let { errorMsg -> "error=$errorMsg" } ?: ""
|
||||
failureCause.message?.let { errorMsg -> "error=$errorMsg" } ?: "",
|
||||
)
|
||||
} else {
|
||||
val responseToLog = response?.bodyAsString()?.let { bodyStr ->
|
||||
@@ -68,7 +68,7 @@ class VertxRestLoggingFormatter(
|
||||
request.method(),
|
||||
uriTransformer.invoke(request.uriToLog()),
|
||||
response?.statusCode() ?: "",
|
||||
responseToLog
|
||||
responseToLog,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ interface VertxHttpRequestSender {
|
||||
* Handy to avoid creating anonymous classes.
|
||||
*/
|
||||
class SimpleVertxHttpRequestSender(
|
||||
private val requestLogger: VertxRequestLogger
|
||||
private val requestLogger: VertxRequestLogger,
|
||||
) : VertxHttpRequestSender {
|
||||
override fun makeRequest(request: HttpRequest<Buffer>): SafeFuture<HttpResponse<Buffer>> {
|
||||
requestLogger.logRequest(request)
|
||||
|
||||
@@ -13,7 +13,7 @@ object VertxHttpRequestSenderFactory {
|
||||
rateLimitBackoffDelay: Duration? = null,
|
||||
retryableErrorCodes: Set<Int> = setOf(429, 503, 504),
|
||||
logFormatter: VertxHttpLoggingFormatter,
|
||||
baseRequestSender: VertxHttpRequestSender
|
||||
baseRequestSender: VertxHttpRequestSender,
|
||||
): VertxHttpRequestSender {
|
||||
val rateLimitedSender = rateLimitBackoffDelay
|
||||
?.let {
|
||||
@@ -21,7 +21,7 @@ object VertxHttpRequestSenderFactory {
|
||||
vertx = vertx,
|
||||
requestSender = baseRequestSender,
|
||||
rateLimitBackoffDelay = rateLimitBackoffDelay,
|
||||
requestLogFormatter = logFormatter
|
||||
requestLogFormatter = logFormatter,
|
||||
)
|
||||
} ?: baseRequestSender
|
||||
val sender = requestRetryConfig
|
||||
@@ -30,7 +30,7 @@ object VertxHttpRequestSenderFactory {
|
||||
vertx = vertx,
|
||||
requestSender = rateLimitedSender,
|
||||
requestRetryConfig = requestRetryConfig,
|
||||
retryableErrorCodes = retryableErrorCodes
|
||||
retryableErrorCodes = retryableErrorCodes,
|
||||
)
|
||||
} ?: rateLimitedSender
|
||||
|
||||
@@ -45,13 +45,13 @@ object VertxHttpRequestSenderFactory {
|
||||
requestResponseLogLevel: Level = Level.TRACE,
|
||||
failuresLogLevel: Level = Level.DEBUG,
|
||||
retryableErrorCodes: Set<Int> = setOf(429, 503, 504),
|
||||
logFormatter: VertxHttpLoggingFormatter
|
||||
logFormatter: VertxHttpLoggingFormatter,
|
||||
): VertxHttpRequestSender {
|
||||
val requestLogger = VertxRestRequestLogger(
|
||||
log = logger,
|
||||
requestResponseLogLevel = requestResponseLogLevel,
|
||||
failuresLogLevel = failuresLogLevel,
|
||||
logFormatter = logFormatter
|
||||
logFormatter = logFormatter,
|
||||
)
|
||||
return createWithBaseSender(
|
||||
vertx = vertx,
|
||||
@@ -59,7 +59,7 @@ object VertxHttpRequestSenderFactory {
|
||||
rateLimitBackoffDelay = rateLimitBackoffDelay,
|
||||
retryableErrorCodes = retryableErrorCodes,
|
||||
logFormatter = logFormatter,
|
||||
baseRequestSender = SimpleVertxHttpRequestSender(requestLogger)
|
||||
baseRequestSender = SimpleVertxHttpRequestSender(requestLogger),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ interface VertxRequestLogger {
|
||||
fun logResponse(
|
||||
request: HttpRequest<Buffer>,
|
||||
response: HttpResponse<Buffer>? = null,
|
||||
failureCause: Throwable? = null
|
||||
failureCause: Throwable? = null,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,18 +19,18 @@ class VertxRestRequestLogger(
|
||||
private val log: Logger,
|
||||
private val logFormatter: VertxHttpLoggingFormatter,
|
||||
private val requestResponseLogLevel: Level = Level.TRACE,
|
||||
private val failuresLogLevel: Level = Level.DEBUG
|
||||
private val failuresLogLevel: Level = Level.DEBUG,
|
||||
) : VertxRequestLogger {
|
||||
constructor(
|
||||
log: Logger,
|
||||
responseLogMaxSize: UInt? = null,
|
||||
requestResponseLogLevel: Level = Level.TRACE,
|
||||
failuresLogLevel: Level = Level.DEBUG
|
||||
failuresLogLevel: Level = Level.DEBUG,
|
||||
) : this(
|
||||
log = log,
|
||||
logFormatter = VertxRestLoggingFormatter(responseLogMaxSize = responseLogMaxSize),
|
||||
requestResponseLogLevel = requestResponseLogLevel,
|
||||
failuresLogLevel = failuresLogLevel
|
||||
failuresLogLevel = failuresLogLevel,
|
||||
)
|
||||
|
||||
private fun logRequest(request: HttpRequest<Buffer>, logLevel: Level = requestResponseLogLevel) {
|
||||
@@ -46,7 +46,7 @@ class VertxRestRequestLogger(
|
||||
override fun logResponse(
|
||||
request: HttpRequest<Buffer>,
|
||||
response: HttpResponse<Buffer>?,
|
||||
failureCause: Throwable?
|
||||
failureCause: Throwable?,
|
||||
) {
|
||||
val isError = response?.statusCode()?.let(::isNotSuccessStatusCode) ?: true
|
||||
val logLevel = if (isError) failuresLogLevel else requestResponseLogLevel
|
||||
|
||||
@@ -17,15 +17,15 @@ class VertxRequestRetrier(
|
||||
backoffDelay = requestRetryConfig.backoffDelay,
|
||||
maxRetries = requestRetryConfig.maxRetries?.toInt(),
|
||||
timeout = requestRetryConfig.timeout,
|
||||
vertx = vertx
|
||||
)
|
||||
vertx = vertx,
|
||||
),
|
||||
) : VertxHttpRequestSender {
|
||||
override fun makeRequest(request: HttpRequest<Buffer>): SafeFuture<HttpResponse<Buffer>> {
|
||||
return asyncRetryer
|
||||
.retry(
|
||||
stopRetriesPredicate = { response: HttpResponse<Buffer> ->
|
||||
response.statusCode() !in retryableErrorCodes
|
||||
}
|
||||
},
|
||||
) {
|
||||
requestSender.makeRequest(request)
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import kotlin.time.Duration
|
||||
|
||||
class BlobScanClient(
|
||||
private val restClient: RestClient<JsonObject>,
|
||||
private val log: Logger = LogManager.getLogger(BlobScanClient::class.java)
|
||||
private val log: Logger = LogManager.getLogger(BlobScanClient::class.java),
|
||||
) : BlobFetcher {
|
||||
fun getBlobById(id: String): SafeFuture<ByteArray> {
|
||||
return restClient
|
||||
@@ -31,7 +31,7 @@ class BlobScanClient(
|
||||
} else {
|
||||
throw RuntimeException(
|
||||
"error fetching blobId=$id " +
|
||||
"errorMessage=${response.body?.getString("message") ?: ""}"
|
||||
"errorMessage=${response.body?.getString("message") ?: ""}",
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ class BlobScanClient(
|
||||
requestRetryConfig: RetryConfig,
|
||||
rateLimitBackoffDelay: Duration? = null,
|
||||
logger: Logger = LogManager.getLogger(BlobScanClient::class.java),
|
||||
responseLogMaxSize: UInt? = 1000u
|
||||
responseLogMaxSize: UInt? = 1000u,
|
||||
): BlobScanClient {
|
||||
val logFormatter = VertxRestLoggingFormatter(responseLogMaxSize = responseLogMaxSize)
|
||||
|
||||
@@ -61,16 +61,16 @@ class BlobScanClient(
|
||||
logger = logger,
|
||||
requestResponseLogLevel = Level.DEBUG,
|
||||
failuresLogLevel = Level.DEBUG,
|
||||
logFormatter = logFormatter
|
||||
logFormatter = logFormatter,
|
||||
)
|
||||
val restClient = VertxRestClient(
|
||||
webClient = WebClient.create(vertx, WebClientOptions().setDefaultsFrom(endpoint)),
|
||||
responseParser = { it.toJsonObject() },
|
||||
requestSender = requestSender
|
||||
requestSender = requestSender,
|
||||
)
|
||||
return BlobScanClient(
|
||||
restClient = restClient,
|
||||
log = logger
|
||||
log = logger,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture
|
||||
// TODO: move to a common module
|
||||
data class RestResponse<T>(
|
||||
val statusCode: Int,
|
||||
val body: T?
|
||||
val body: T?,
|
||||
)
|
||||
|
||||
interface RestClient<Response> {
|
||||
@@ -20,13 +20,13 @@ class VertxRestClient<Response>(
|
||||
private val webClient: WebClient,
|
||||
private val responseParser: (Buffer) -> Response,
|
||||
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> {
|
||||
override fun get(path: String): SafeFuture<RestResponse<Response>> {
|
||||
return requestSender.makeRequest(
|
||||
webClient
|
||||
.get(path)
|
||||
.apply { requestHeaders.forEach(::putHeader) }
|
||||
.apply { requestHeaders.forEach(::putHeader) },
|
||||
)
|
||||
.thenApply { response ->
|
||||
val parsedResponse = response.body()?.let(responseParser)
|
||||
|
||||
@@ -16,17 +16,25 @@ import kotlin.time.TimeSource
|
||||
fun httpResponse(
|
||||
statusCode: Int = 200,
|
||||
statusMessage: String = "OK",
|
||||
body: Buffer = Buffer.buffer()
|
||||
body: Buffer = Buffer.buffer(),
|
||||
): HttpResponse<Buffer> {
|
||||
return HttpResponseImpl(
|
||||
/* version = */ HttpVersion.HTTP_1_1,
|
||||
/* statusCode = */ statusCode,
|
||||
/* statusMessage = */ statusMessage,
|
||||
/* headers = */ HeadersMultiMap(),
|
||||
/* trailers = */ HeadersMultiMap(),
|
||||
/* cookies = */ emptyList<String>(),
|
||||
/* body = */ body,
|
||||
/* redirects = */ emptyList<String>()
|
||||
/* version = */
|
||||
HttpVersion.HTTP_1_1,
|
||||
/* statusCode = */
|
||||
statusCode,
|
||||
/* statusMessage = */
|
||||
statusMessage,
|
||||
/* headers = */
|
||||
HeadersMultiMap(),
|
||||
/* trailers = */
|
||||
HeadersMultiMap(),
|
||||
/* cookies = */
|
||||
emptyList<String>(),
|
||||
/* body = */
|
||||
body,
|
||||
/* redirects = */
|
||||
emptyList<String>(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -35,8 +43,8 @@ class FakeRequestSender(
|
||||
VertxRestRequestLogger(
|
||||
responseLogMaxSize = null,
|
||||
requestResponseLogLevel = Level.DEBUG,
|
||||
log = LogManager.getLogger(FakeRequestSender::class.java)
|
||||
)
|
||||
log = LogManager.getLogger(FakeRequestSender::class.java),
|
||||
),
|
||||
) : VertxHttpRequestSender {
|
||||
private val monotonicClock = TimeSource.Monotonic
|
||||
private var lastRequestTime = monotonicClock.markNow()
|
||||
|
||||
@@ -23,7 +23,7 @@ class StaticVertxHttpRequestRateLimiterTest {
|
||||
vertx = vertx,
|
||||
requestSender = reqSender,
|
||||
rateLimitBackoffDelay = rateLimitBackoffDelay,
|
||||
requestLogFormatter = VertxRestLoggingFormatter()
|
||||
requestLogFormatter = VertxRestLoggingFormatter(),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -28,10 +28,10 @@ class VertxHttpRequestRateLimiterAndRetryTest {
|
||||
requestRetryConfig = RetryConfig(
|
||||
maxRetries = 5u,
|
||||
backoffDelay = 10.milliseconds,
|
||||
timeout = rateLimitBackoffDelay * 30
|
||||
timeout = rateLimitBackoffDelay * 30,
|
||||
),
|
||||
rateLimitBackoffDelay = rateLimitBackoffDelay,
|
||||
logFormatter = VertxRestLoggingFormatter(responseLogMaxSize = 1000u)
|
||||
logFormatter = VertxRestLoggingFormatter(responseLogMaxSize = 1000u),
|
||||
)
|
||||
// Warn: this does not work in io.github.hakky54:logcaptor
|
||||
// don't have time to dig into it now. disabling it for now
|
||||
|
||||
@@ -13,7 +13,7 @@ class VertxRestLoggingFormatterTest {
|
||||
val request = WebClient.create(
|
||||
Vertx.vertx(),
|
||||
WebClientOptions()
|
||||
.setDefaultsFrom(URI("http://service:9876/"))
|
||||
.setDefaultsFrom(URI("http://service:9876/")),
|
||||
)
|
||||
.get("/users/1?appKey=SOME_APP_KEY")
|
||||
|
||||
@@ -21,7 +21,7 @@ class VertxRestLoggingFormatterTest {
|
||||
return VertxRestLoggingFormatter(
|
||||
includeFullUri = includeFullUri,
|
||||
uriTransformer = { it.replace("SOME_APP_KEY", "***") },
|
||||
responseLogMaxSize = null
|
||||
responseLogMaxSize = null,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class VertxRestLoggingFormatterTest {
|
||||
val response = httpResponse(
|
||||
statusCode = 200,
|
||||
statusMessage = "OK",
|
||||
body = Buffer.buffer("some-response-body")
|
||||
body = Buffer.buffer("some-response-body"),
|
||||
)
|
||||
|
||||
assertThat(formatter(includeFullUri = false).toLogString(request, response))
|
||||
|
||||
@@ -21,7 +21,7 @@ class VertxRestRequestLoggerTest {
|
||||
override fun toLogString(
|
||||
request: HttpRequest<Buffer>,
|
||||
response: HttpResponse<Buffer>?,
|
||||
failureCause: Throwable?
|
||||
failureCause: Throwable?,
|
||||
): String {
|
||||
return "response-log-string"
|
||||
}
|
||||
@@ -29,14 +29,14 @@ class VertxRestRequestLoggerTest {
|
||||
|
||||
fun setUpLogger(
|
||||
// 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> {
|
||||
val logCaptor: LogCaptor = LogCaptor.forName(loggerName)
|
||||
return VertxRestRequestLogger(
|
||||
log = LogManager.getLogger(loggerName),
|
||||
logFormatter = FakeLogFormatter(),
|
||||
requestResponseLogLevel = Level.TRACE,
|
||||
failuresLogLevel = Level.DEBUG
|
||||
failuresLogLevel = Level.DEBUG,
|
||||
) to logCaptor
|
||||
}
|
||||
|
||||
|
||||
@@ -32,13 +32,13 @@ class BlobScanClientTest {
|
||||
fun setUp(vertx: Vertx) {
|
||||
wiremock = WireMockServer(
|
||||
WireMockConfiguration.options()
|
||||
.dynamicPort()
|
||||
.dynamicPort(),
|
||||
)
|
||||
.apply {
|
||||
addMockServiceRequestListener(object : RequestListener {
|
||||
override fun requestReceived(
|
||||
request: com.github.tomakehurst.wiremock.http.Request,
|
||||
response: com.github.tomakehurst.wiremock.http.Response
|
||||
response: com.github.tomakehurst.wiremock.http.Response,
|
||||
) {
|
||||
// to debug
|
||||
// println("request: ${request.url}")
|
||||
@@ -55,8 +55,8 @@ class BlobScanClientTest {
|
||||
requestRetryConfig = RetryConfig(
|
||||
backoffDelay = 10.milliseconds,
|
||||
maxRetries = 5u,
|
||||
timeout = 5.seconds
|
||||
)
|
||||
timeout = 5.seconds,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -78,8 +78,8 @@ class BlobScanClientTest {
|
||||
.willReturn(
|
||||
WireMock.ok()
|
||||
.withHeader("Content-type", "application/json")
|
||||
.withBody(successResponseBody(blobId, blobData))
|
||||
)
|
||||
.withBody(successResponseBody(blobId, blobData)),
|
||||
),
|
||||
)
|
||||
|
||||
assertThat(blobScanClient.getBlobById(blobId).get().encodeHex()).isEqualTo(blobData)
|
||||
@@ -99,9 +99,9 @@ class BlobScanClientTest {
|
||||
.withBody(
|
||||
"""
|
||||
{"message":"No blob with versioned hash or kzg commitment '$blobId'.","code":"NOT_FOUND"}
|
||||
""".trimIndent()
|
||||
)
|
||||
)
|
||||
""".trimIndent(),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
assertThatThrownBy { blobScanClient.getBlobById(blobId).get() }
|
||||
@@ -117,22 +117,22 @@ class BlobScanClientTest {
|
||||
WireMock.get("/blobs/$blobId")
|
||||
.inScenario("SERVER_ERROR")
|
||||
.willReturn(WireMock.status(503))
|
||||
.willSetStateTo("SERVER_ERROR_1")
|
||||
.willSetStateTo("SERVER_ERROR_1"),
|
||||
)
|
||||
wiremock.stubFor(
|
||||
WireMock.get("/blobs/$blobId")
|
||||
.inScenario("SERVER_ERROR")
|
||||
.whenScenarioStateIs("SERVER_ERROR_1")
|
||||
.willReturn(WireMock.status(503))
|
||||
.willSetStateTo("SERVER_OK")
|
||||
.willSetStateTo("SERVER_OK"),
|
||||
)
|
||||
wiremock.stubFor(
|
||||
WireMock.get("/blobs/$blobId")
|
||||
.inScenario("SERVER_ERROR")
|
||||
.whenScenarioStateIs("SERVER_OK")
|
||||
.willReturn(
|
||||
WireMock.okJson(successResponseBody(blobId, blobData))
|
||||
)
|
||||
WireMock.okJson(successResponseBody(blobId, blobData)),
|
||||
),
|
||||
)
|
||||
|
||||
assertThat(blobScanClient.getBlobById(blobId).get().encodeHex()).isEqualTo(blobData)
|
||||
@@ -140,7 +140,7 @@ class BlobScanClientTest {
|
||||
|
||||
private fun successResponseBody(
|
||||
blobId: String,
|
||||
blobData: String
|
||||
blobData: String,
|
||||
): String {
|
||||
return """
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture
|
||||
import java.net.URI
|
||||
|
||||
class VertxTransactionDetailsClient internal constructor(
|
||||
private val jsonRpcClient: JsonRpcV2Client
|
||||
private val jsonRpcClient: JsonRpcV2Client,
|
||||
) : TransactionDetailsClient {
|
||||
|
||||
companion object {
|
||||
@@ -21,14 +21,14 @@ class VertxTransactionDetailsClient internal constructor(
|
||||
jsonRpcClientFactory: JsonRpcClientFactory,
|
||||
endpoint: URI,
|
||||
retryConfig: RequestRetryConfig,
|
||||
logger: Logger = LogManager.getLogger(TransactionDetailsClient::class.java)
|
||||
logger: Logger = LogManager.getLogger(TransactionDetailsClient::class.java),
|
||||
): VertxTransactionDetailsClient {
|
||||
return VertxTransactionDetailsClient(
|
||||
jsonRpcClientFactory.createJsonRpcV2Client(
|
||||
endpoints = listOf(endpoint),
|
||||
retryConfig = retryConfig,
|
||||
log = logger
|
||||
)
|
||||
log = logger,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ class VertxTransactionDetailsClient internal constructor(
|
||||
?.toList()
|
||||
?.map { it.asText().decodeHex() }
|
||||
?: emptyList()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ class StateRecoveryE2ETest {
|
||||
fun beforeEach(vertx: Vertx) {
|
||||
val jsonRpcFactory = VertxHttpJsonRpcClientFactory(
|
||||
vertx = vertx,
|
||||
metricsFacade = MicrometerMetricsFacade(SimpleMeterRegistry())
|
||||
metricsFacade = MicrometerMetricsFacade(SimpleMeterRegistry()),
|
||||
)
|
||||
|
||||
stateManagerClient = StateManagerV1JsonRpcClient.create(
|
||||
@@ -63,10 +63,10 @@ class StateRecoveryE2ETest {
|
||||
maxInflightRequestsPerClient = 1U,
|
||||
requestRetry = RequestRetryConfig(
|
||||
backoffDelay = 10.milliseconds,
|
||||
timeout = 2.seconds
|
||||
timeout = 2.seconds,
|
||||
),
|
||||
zkStateManagerVersion = "2.3.0",
|
||||
logger = LogManager.getLogger("test.clients.l1.state-manager")
|
||||
logger = LogManager.getLogger("test.clients.l1.state-manager"),
|
||||
)
|
||||
|
||||
configureLoggers(
|
||||
@@ -80,7 +80,7 @@ class StateRecoveryE2ETest {
|
||||
"test.clients.l1.linea-contract" to Level.INFO,
|
||||
"test.clients.l1.events-fetcher" 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(
|
||||
command = "make start-env-with-staterecovery",
|
||||
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()
|
||||
log.debug("stack restarted")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should recover from middle of chain and be resilient to node restarts`(
|
||||
vertx: Vertx
|
||||
vertx: Vertx,
|
||||
) {
|
||||
// Part A:
|
||||
// we shall have multiple finalizations on L1
|
||||
@@ -128,15 +128,15 @@ class StateRecoveryE2ETest {
|
||||
Web3jClientManager.buildL1Client(
|
||||
log = LogManager.getLogger("test.clients.l1.events-fetcher"),
|
||||
requestResponseLogLevel = Level.TRACE,
|
||||
failuresLogLevel = Level.WARN
|
||||
failuresLogLevel = Level.WARN,
|
||||
),
|
||||
requestRetryConfig = RetryConfig.noRetries,
|
||||
vertx = null
|
||||
vertx = null,
|
||||
),
|
||||
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)
|
||||
log.info("starting test flow: besu staterecovery block={}", web3jElClient.ethBlockNumber().send().blockNumber)
|
||||
@@ -167,7 +167,7 @@ class StateRecoveryE2ETest {
|
||||
command = "make staterecovery-replay-from-block " +
|
||||
"L1_ROLLUP_CONTRACT_ADDRESS=$localStackL1ContractAddress " +
|
||||
"STATERECOVERY_OVERRIDE_START_BLOCK_NUMBER=$stateRecoveryStartBlockNumber",
|
||||
log = log
|
||||
log = log,
|
||||
).get()
|
||||
// No Errors should be logged in Besu
|
||||
assertThat(getBesuErrorLogs()).isEmpty()
|
||||
@@ -178,7 +178,7 @@ class StateRecoveryE2ETest {
|
||||
web3jElClient,
|
||||
stateManagerClient,
|
||||
lastFinalizationA.event.endBlockNumber,
|
||||
lastFinalizationA.event.finalStateRootHash
|
||||
lastFinalizationA.event.finalStateRootHash,
|
||||
)
|
||||
// No Errors should be logged in Besu
|
||||
assertThat(getBesuErrorLogs()).isEmpty()
|
||||
@@ -200,7 +200,7 @@ class StateRecoveryE2ETest {
|
||||
web3jElClient,
|
||||
stateManagerClient,
|
||||
lastFinalizationB.event.endBlockNumber,
|
||||
lastFinalizationB.event.finalStateRootHash
|
||||
lastFinalizationB.event.finalStateRootHash,
|
||||
)
|
||||
// No Errors should be logged in Besu
|
||||
assertThat(getBesuErrorLogs()).isEmpty()
|
||||
@@ -210,7 +210,7 @@ class StateRecoveryE2ETest {
|
||||
log.info("Restarting zkbesu-shomei node")
|
||||
execCommandAndAssertSuccess(
|
||||
command = "docker restart -s 9 zkbesu-shomei-sr",
|
||||
log = log
|
||||
log = log,
|
||||
).get()
|
||||
// No Errors should be logged in Besu
|
||||
assertThat(getBesuErrorLogs()).isEmpty()
|
||||
@@ -237,31 +237,36 @@ class StateRecoveryE2ETest {
|
||||
web3jElClient,
|
||||
stateManagerClient,
|
||||
lastFinalizationC.event.endBlockNumber,
|
||||
lastFinalizationC.event.finalStateRootHash
|
||||
lastFinalizationC.event.finalStateRootHash,
|
||||
)
|
||||
// No Errors should be logged in Besu
|
||||
assertThat(getBesuErrorLogs()).isEmpty()
|
||||
}
|
||||
|
||||
private fun sendTxToL2(
|
||||
keepSendingPredicate: () -> Boolean
|
||||
keepSendingPredicate: () -> Boolean,
|
||||
) {
|
||||
val account = L2AccountManager.generateAccount()
|
||||
val txManager = L2AccountManager.getTransactionManager(account)
|
||||
Thread {
|
||||
while (keepSendingPredicate()) {
|
||||
val txHash = txManager.sendTransaction(
|
||||
/*gasPrice*/ 150UL.gwei.toBigInteger(),
|
||||
/*gasLimit*/ 25_000UL.toBigInteger(),
|
||||
/*to*/ account.address,
|
||||
/*data*/ "",
|
||||
/*value*/ 1UL.toBigInteger()
|
||||
/*gasPrice*/
|
||||
150UL.gwei.toBigInteger(),
|
||||
/*gasLimit*/
|
||||
25_000UL.toBigInteger(),
|
||||
/*to*/
|
||||
account.address,
|
||||
/*data*/
|
||||
"",
|
||||
/*value*/
|
||||
1UL.toBigInteger(),
|
||||
).transactionHash
|
||||
log.trace("sent tx to L2, txHash={}", txHash)
|
||||
Web3jClientManager.l2Client.waitForTxReceipt(
|
||||
txHash = txHash,
|
||||
timeout = 5.seconds,
|
||||
pollingInterval = 500.milliseconds
|
||||
pollingInterval = 500.milliseconds,
|
||||
)
|
||||
}
|
||||
}.start()
|
||||
|
||||
@@ -39,7 +39,7 @@ class LineaSubmissionEventsClientIntTest {
|
||||
private lateinit var submissionEventsFetcher: LineaRollupSubmissionEventsClient
|
||||
|
||||
private fun setupTest(
|
||||
vertx: Vertx
|
||||
vertx: Vertx,
|
||||
) {
|
||||
configureLoggers(
|
||||
rootLevel = Level.INFO,
|
||||
@@ -47,7 +47,7 @@ class LineaSubmissionEventsClientIntTest {
|
||||
"test.clients.l1.executionlayer" to Level.INFO,
|
||||
"test.clients.l1.web3j-default" 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()
|
||||
@@ -57,13 +57,13 @@ class LineaSubmissionEventsClientIntTest {
|
||||
blobsResponsesDir = "$testDataDir/compression/responses",
|
||||
aggregationsResponsesDir = "$testDataDir/aggregation/responses",
|
||||
numberOfAggregations = 7,
|
||||
extraBlobsWithoutAggregation = 3
|
||||
extraBlobsWithoutAggregation = 3,
|
||||
)
|
||||
// wait smc deployment finishes
|
||||
rollupDeploymentResult = rollupDeploymentFuture.get()
|
||||
submissionEventsFetcher = createSubmissionEventsClient(
|
||||
vertx = vertx,
|
||||
contractAddress = rollupDeploymentResult.contractAddress
|
||||
contractAddress = rollupDeploymentResult.contractAddress,
|
||||
)
|
||||
|
||||
submitBlobsAndAggregationsAndWaitExecution(
|
||||
@@ -71,24 +71,24 @@ class LineaSubmissionEventsClientIntTest {
|
||||
contractClientForAggregationSubmission = connectToLineaRollupContract(
|
||||
contractAddress = rollupDeploymentResult.contractAddress,
|
||||
transactionManager = rollupDeploymentResult.rollupOperators[1].txManager,
|
||||
smartContractErrors = lineaRollupContractErrors
|
||||
smartContractErrors = lineaRollupContractErrors,
|
||||
),
|
||||
aggregationsAndBlobs = aggregationsAndBlobs,
|
||||
blobChunksMaxSize = 9,
|
||||
l1Web3jClient = Web3jClientManager.l1Client,
|
||||
waitTimeout = 4.minutes
|
||||
waitTimeout = 4.minutes,
|
||||
)
|
||||
}
|
||||
|
||||
private fun createSubmissionEventsClient(
|
||||
vertx: Vertx,
|
||||
contractAddress: String
|
||||
contractAddress: String,
|
||||
): LineaRollupSubmissionEventsClient {
|
||||
val log = LogManager.getLogger("test.clients.l1.events-fetcher")
|
||||
val eventsFetcherWeb3jClient = Web3jClientManager.buildL1Client(
|
||||
log = log,
|
||||
requestResponseLogLevel = Level.DEBUG,
|
||||
failuresLogLevel = Level.WARN
|
||||
failuresLogLevel = Level.WARN,
|
||||
)
|
||||
return LineaSubmissionEventsClientImpl(
|
||||
logsSearcher = EthLogsSearcherImpl(
|
||||
@@ -96,16 +96,16 @@ class LineaSubmissionEventsClientIntTest {
|
||||
ethApiClient = createEthApiClient(
|
||||
web3jClient = eventsFetcherWeb3jClient,
|
||||
requestRetryConfig = RetryConfig.noRetries,
|
||||
vertx = null
|
||||
vertx = null,
|
||||
),
|
||||
config = EthLogsSearcherImpl.Config(
|
||||
loopSuccessBackoffDelay = 1.milliseconds
|
||||
loopSuccessBackoffDelay = 1.milliseconds,
|
||||
),
|
||||
log = log
|
||||
log = log,
|
||||
),
|
||||
smartContractAddress = contractAddress,
|
||||
l1LatestSearchBlock = BlockParameter.Tag.LATEST,
|
||||
logsBlockChunkSize = 100
|
||||
logsBlockChunkSize = 100,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -125,8 +125,8 @@ class LineaSubmissionEventsClientIntTest {
|
||||
submissionEventsFetcher
|
||||
.findFinalizationAndDataSubmissionV3Events(
|
||||
fromL1BlockNumber = BlockParameter.Tag.EARLIEST,
|
||||
finalizationStartBlockNumber = expectedFinalizationEvent.startBlockNumber
|
||||
)
|
||||
finalizationStartBlockNumber = expectedFinalizationEvent.startBlockNumber,
|
||||
),
|
||||
)
|
||||
.succeedsWithin(1.minutes.toJavaDuration())
|
||||
.extracting { submissionEvents ->
|
||||
@@ -146,8 +146,8 @@ class LineaSubmissionEventsClientIntTest {
|
||||
submissionEventsFetcher
|
||||
.findFinalizationAndDataSubmissionV3Events(
|
||||
fromL1BlockNumber = BlockParameter.Tag.EARLIEST,
|
||||
finalizationStartBlockNumber = invalidStartBlockNumber
|
||||
).get()
|
||||
finalizationStartBlockNumber = invalidStartBlockNumber,
|
||||
).get(),
|
||||
)
|
||||
.isNull()
|
||||
}
|
||||
@@ -159,7 +159,7 @@ class LineaSubmissionEventsClientIntTest {
|
||||
submissionEventsFetcher
|
||||
.findFinalizationAndDataSubmissionV3EventsContainingL2BlockNumber(
|
||||
fromL1BlockNumber = BlockParameter.Tag.EARLIEST,
|
||||
l2BlockNumber = invalidStartBlockNumber
|
||||
l2BlockNumber = invalidStartBlockNumber,
|
||||
).get()
|
||||
.also { result ->
|
||||
assertThat(result).isNotNull
|
||||
@@ -169,7 +169,7 @@ class LineaSubmissionEventsClientIntTest {
|
||||
}
|
||||
|
||||
private fun getExpectedSubmissionEventsFromRecords(
|
||||
aggregationsAndBlobs: List<AggregationAndBlobs>
|
||||
aggregationsAndBlobs: List<AggregationAndBlobs>,
|
||||
): List<Pair<DataFinalizedV3, List<DataSubmittedV3>>> {
|
||||
return aggregationsAndBlobs
|
||||
.filter { it.aggregation != null }
|
||||
@@ -180,7 +180,7 @@ class LineaSubmissionEventsClientIntTest {
|
||||
DataSubmittedV3(
|
||||
parentShnarf = blobsChunk.first().blobCompressionProof!!.prevShnarf,
|
||||
shnarf = blobsChunk.last().expectedShnarf,
|
||||
finalStateRootHash = blobsChunk.last().blobCompressionProof!!.finalStateRootHash
|
||||
finalStateRootHash = blobsChunk.last().blobCompressionProof!!.finalStateRootHash,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ class LineaSubmissionEventsClientIntTest {
|
||||
endBlockNumber = aggregation.endBlockNumber,
|
||||
shnarf = aggBlobs.last().expectedShnarf,
|
||||
parentStateRootHash = aggBlobs.first().blobCompressionProof!!.parentStateRootHash,
|
||||
finalStateRootHash = aggBlobs.last().blobCompressionProof!!.finalStateRootHash
|
||||
finalStateRootHash = aggBlobs.last().blobCompressionProof!!.finalStateRootHash,
|
||||
) to expectedDataSubmittedEvents
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,12 +65,12 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
|
||||
blobsResponsesDir = "$testDataDir/compression/responses",
|
||||
aggregationsResponsesDir = "$testDataDir/aggregation/responses",
|
||||
numberOfAggregations = 4,
|
||||
extraBlobsWithoutAggregation = 0
|
||||
extraBlobsWithoutAggregation = 0,
|
||||
)
|
||||
fakeExecutionLayerClient = FakeExecutionLayerClient(
|
||||
headBlock = BlockNumberAndHash(number = 0uL, hash = ByteArray(32) { 0 }),
|
||||
initialStateRecoverStartBlockNumber = null,
|
||||
loggerName = "test.fake.clients.l1.fake-execution-layer"
|
||||
loggerName = "test.fake.clients.l1.fake-execution-layer",
|
||||
)
|
||||
fakeStateManagerClient =
|
||||
FakeStateManagerClientBasedOnBlobsRecords(blobRecords = aggregationsAndBlobs.flatMap { it.blobs })
|
||||
@@ -84,7 +84,7 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
|
||||
l1PollingInterval = 100.milliseconds,
|
||||
l1getLogsChunkSize = 1000u,
|
||||
executionClientPollingInterval = 1.seconds,
|
||||
smartContractAddress = rollupDeploymentResult.contractAddress
|
||||
smartContractAddress = rollupDeploymentResult.contractAddress,
|
||||
)
|
||||
|
||||
appClients = createAppClients(
|
||||
@@ -93,14 +93,14 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
|
||||
l1RpcEndpoint = URI(l1RpcUrl),
|
||||
l1RequestRetryConfig = RetryConfig(backoffDelay = 2.seconds),
|
||||
blobScanEndpoint = URI(blobScanUrl),
|
||||
stateManagerClientEndpoint = URI("http://it-does-not-matter:5432")
|
||||
stateManagerClientEndpoint = URI("http://it-does-not-matter:5432"),
|
||||
)
|
||||
|
||||
contractClientForBlobSubmissions = rollupDeploymentResult.rollupOperatorClient
|
||||
contractClientForAggregationSubmissions = connectToLineaRollupContract(
|
||||
rollupDeploymentResult.contractAddress,
|
||||
rollupDeploymentResult.rollupOperators[1].txManager,
|
||||
smartContractErrors = lineaRollupContractErrors
|
||||
smartContractErrors = lineaRollupContractErrors,
|
||||
)
|
||||
|
||||
configureLoggers(
|
||||
@@ -113,12 +113,12 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
|
||||
"test.fake.clients.l1.fake-execution-layer" to Level.DEBUG,
|
||||
"test.clients.l1.web3j-default" 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(
|
||||
debugForceSyncStopBlockNumber: ULong? = null
|
||||
debugForceSyncStopBlockNumber: ULong? = null,
|
||||
): StateRecoveryApp {
|
||||
return StateRecoveryApp(
|
||||
vertx = vertx,
|
||||
@@ -130,15 +130,15 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
|
||||
blockHeaderStaticFields = BlockHeaderStaticFields.localDev,
|
||||
lineaContractClient = appClients.lineaContractClient,
|
||||
config = appConfigs.copy(
|
||||
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber
|
||||
)
|
||||
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun submitDataToL1ContactAndWaitExecution(
|
||||
aggregationsAndBlobs: List<AggregationAndBlobs> = this.aggregationsAndBlobs,
|
||||
blobChunksSize: Int = 9,
|
||||
waitTimeout: Duration = 4.minutes
|
||||
waitTimeout: Duration = 4.minutes,
|
||||
) {
|
||||
submitBlobsAndAggregationsAndWaitExecution(
|
||||
contractClientForBlobSubmission = contractClientForBlobSubmissions,
|
||||
@@ -148,8 +148,8 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
|
||||
waitTimeout = waitTimeout,
|
||||
l1Web3jClient = createWeb3jHttpClient(
|
||||
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.1 recoveryStartBlockNumber > headBlockNumber: pull for head block number until is reached and start recovery there
|
||||
2.2 recoveryStartBlockNumber <= headBlockNumber: resume recovery from headBlockNumber
|
||||
*/
|
||||
*/
|
||||
@Test
|
||||
fun `when state recovery disabled and is starting from genesis`() {
|
||||
instantiateStateRecoveryApp().start().get()
|
||||
@@ -180,8 +180,8 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
|
||||
.isEqualTo(
|
||||
StateRecoveryStatus(
|
||||
headBlockNumber = lastAggregation!!.endBlockNumber,
|
||||
stateRecoverStartBlockNumber = 1UL
|
||||
)
|
||||
stateRecoverStartBlockNumber = 1UL,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -204,16 +204,16 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
|
||||
log.debug(
|
||||
"finalizations={} finalizationToStartRecoveryFrom={}",
|
||||
aggregationsAndBlobs.map { it.aggregation?.intervalString() },
|
||||
finalizationToResumeFrom.intervalString()
|
||||
finalizationToResumeFrom.intervalString(),
|
||||
)
|
||||
|
||||
submitDataToL1ContactAndWaitExecution(
|
||||
aggregationsAndBlobs = finalizationsBeforeCutOff
|
||||
aggregationsAndBlobs = finalizationsBeforeCutOff,
|
||||
)
|
||||
|
||||
fakeExecutionLayerClient.headBlock = BlockNumberAndHash(
|
||||
number = 1UL,
|
||||
hash = ByteArray(32) { 0 }
|
||||
hash = ByteArray(32) { 0 },
|
||||
)
|
||||
|
||||
val lastFinalizedBlockNumber = finalizationsBeforeCutOff.last().aggregation!!.endBlockNumber
|
||||
@@ -227,8 +227,8 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
|
||||
assertThat(fakeExecutionLayerClient.stateRecoverStatus).isEqualTo(
|
||||
StateRecoveryStatus(
|
||||
headBlockNumber = 1UL,
|
||||
stateRecoverStartBlockNumber = expectedStateRecoverStartBlockNumber
|
||||
)
|
||||
stateRecoverStartBlockNumber = expectedStateRecoverStartBlockNumber,
|
||||
),
|
||||
)
|
||||
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
|
||||
fakeExecutionLayerClient.headBlock = BlockNumberAndHash(
|
||||
number = lastFinalizedBlockNumber,
|
||||
hash = ByteArray(32) { 0 }
|
||||
hash = ByteArray(32) { 0 },
|
||||
)
|
||||
|
||||
// continue finalizing the rest of the aggregations
|
||||
submitDataToL1ContactAndWaitExecution(
|
||||
aggregationsAndBlobs = finalizationsAfterCutOff
|
||||
aggregationsAndBlobs = finalizationsAfterCutOff,
|
||||
)
|
||||
|
||||
val lastAggregation = aggregationsAndBlobs.findLast { it.aggregation != null }!!.aggregation
|
||||
@@ -277,18 +277,18 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
|
||||
log.debug(
|
||||
"finalizations={} finalizationToStartRecoveryFrom={}",
|
||||
aggregationsAndBlobs.map { it.aggregation?.intervalString() },
|
||||
finalizationToResumeFrom.intervalString()
|
||||
finalizationToResumeFrom.intervalString(),
|
||||
)
|
||||
|
||||
submitDataToL1ContactAndWaitExecution(
|
||||
aggregationsAndBlobs = finalizationsBeforeCutOff
|
||||
aggregationsAndBlobs = finalizationsBeforeCutOff,
|
||||
)
|
||||
|
||||
// set execution layer head block after latest finalization
|
||||
val headBlockNumberAtStart = finalizationsBeforeCutOff.last().aggregation!!.endBlockNumber + 1UL
|
||||
fakeExecutionLayerClient.headBlock = BlockNumberAndHash(
|
||||
number = headBlockNumberAtStart,
|
||||
hash = ByteArray(32) { 0 }
|
||||
hash = ByteArray(32) { 0 },
|
||||
)
|
||||
instantiateStateRecoveryApp().start().get()
|
||||
await()
|
||||
@@ -298,15 +298,15 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
|
||||
assertThat(fakeExecutionLayerClient.stateRecoverStatus).isEqualTo(
|
||||
StateRecoveryStatus(
|
||||
headBlockNumber = headBlockNumberAtStart,
|
||||
stateRecoverStartBlockNumber = headBlockNumberAtStart + 1UL
|
||||
)
|
||||
stateRecoverStartBlockNumber = headBlockNumberAtStart + 1UL,
|
||||
),
|
||||
)
|
||||
log.debug("stateRecoverStatus={}", fakeExecutionLayerClient.stateRecoverStatus)
|
||||
}
|
||||
|
||||
// continue finalizing the rest of the aggregations
|
||||
submitDataToL1ContactAndWaitExecution(
|
||||
aggregationsAndBlobs = finalizationsAfterCutOff
|
||||
aggregationsAndBlobs = finalizationsAfterCutOff,
|
||||
)
|
||||
|
||||
val lastAggregation = aggregationsAndBlobs.findLast { it.aggregation != null }!!.aggregation
|
||||
@@ -318,8 +318,8 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
|
||||
.isEqualTo(
|
||||
StateRecoveryStatus(
|
||||
headBlockNumber = lastAggregation!!.endBlockNumber,
|
||||
stateRecoverStartBlockNumber = headBlockNumberAtStart + 1UL
|
||||
)
|
||||
stateRecoverStartBlockNumber = headBlockNumberAtStart + 1UL,
|
||||
),
|
||||
)
|
||||
}
|
||||
// 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`() {
|
||||
fakeStateManagerClient.setBlockStateRootHash(
|
||||
aggregationsAndBlobs[1].aggregation!!.endBlockNumber,
|
||||
ByteArray(32) { 1 }
|
||||
ByteArray(32) { 1 },
|
||||
)
|
||||
log.debug(
|
||||
"aggregations={} forcedMismatchAggregation={}",
|
||||
aggregationsAndBlobs.map { it.aggregation?.intervalString() },
|
||||
aggregationsAndBlobs[1].aggregation!!.intervalString()
|
||||
aggregationsAndBlobs[1].aggregation!!.intervalString(),
|
||||
)
|
||||
|
||||
val stateRecoverApp = instantiateStateRecoveryApp()
|
||||
@@ -368,7 +368,7 @@ class StateRecoveryAppWithFakeExecutionClientIntTest {
|
||||
log.debug(
|
||||
"headBlockNumber={} forceSyncStopBlockNumber={}",
|
||||
fakeExecutionLayerClient.headBlock.number,
|
||||
debugForceSyncStopBlockNumber
|
||||
debugForceSyncStopBlockNumber,
|
||||
)
|
||||
assertThat(fakeExecutionLayerClient.headBlock.number).isGreaterThanOrEqualTo(debugForceSyncStopBlockNumber)
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
|
||||
private val testDataDir = "testdata/coordinator/prover/v3/stateRecovery"
|
||||
private val aggregationsAndBlobs: List<AggregationAndBlobs> = loadBlobsAndAggregationsSortedAndGrouped(
|
||||
blobsResponsesDir = "$testDataDir/compression/responses",
|
||||
aggregationsResponsesDir = "$testDataDir/aggregation/responses"
|
||||
aggregationsResponsesDir = "$testDataDir/aggregation/responses",
|
||||
)
|
||||
private lateinit var rollupDeploymentResult: LineaRollupDeploymentResult
|
||||
private lateinit var contractClientForBlobSubmission: LineaRollupSmartContractClient
|
||||
@@ -54,7 +54,7 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
|
||||
fun beforeEach(vertx: Vertx) {
|
||||
val jsonRpcFactory = VertxHttpJsonRpcClientFactory(
|
||||
vertx = vertx,
|
||||
metricsFacade = MicrometerMetricsFacade(SimpleMeterRegistry())
|
||||
metricsFacade = MicrometerMetricsFacade(SimpleMeterRegistry()),
|
||||
)
|
||||
|
||||
stateManagerClient = StateManagerV1JsonRpcClient.create(
|
||||
@@ -63,10 +63,10 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
|
||||
maxInflightRequestsPerClient = 1U,
|
||||
requestRetry = RequestRetryConfig(
|
||||
backoffDelay = 1.seconds,
|
||||
timeout = 4.seconds
|
||||
timeout = 4.seconds,
|
||||
),
|
||||
zkStateManagerVersion = "2.3.0",
|
||||
logger = LogManager.getLogger("test.clients.l1.state-manager")
|
||||
logger = LogManager.getLogger("test.clients.l1.state-manager"),
|
||||
)
|
||||
|
||||
configureLoggers(
|
||||
@@ -74,7 +74,7 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
|
||||
log.name to Level.DEBUG,
|
||||
"net.consensys.linea.contract.Web3JContractAsyncHelper" to Level.WARN, // silence noisy gasPrice Caps logs
|
||||
"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,
|
||||
// index 0 is the first operator in rollupOperatorClient
|
||||
rollupDeploymentResult.rollupOperators[1].txManager,
|
||||
smartContractErrors = lineaRollupContractErrors
|
||||
smartContractErrors = lineaRollupContractErrors,
|
||||
)
|
||||
log.info("starting stack for recovery of state pushed to L1")
|
||||
val staterecoveryNodesStartFuture = execCommandAndAssertSuccess(
|
||||
@@ -98,7 +98,7 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
|
||||
"L1_ROLLUP_CONTRACT_ADDRESS=${rollupDeploymentResult.contractAddress} " +
|
||||
"STATERECOVERY_OVERRIDE_START_BLOCK_NUMBER=1",
|
||||
timeout = 1.minutes,
|
||||
log = log
|
||||
log = log,
|
||||
).thenPeek {
|
||||
log.info("make staterecovery-replay-from-block executed")
|
||||
}
|
||||
@@ -114,7 +114,7 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
|
||||
blobChunksMaxSize = 9,
|
||||
l1Web3jClient = Web3jClientManager.l1Client,
|
||||
waitTimeout = 4.minutes,
|
||||
log = log
|
||||
log = log,
|
||||
)
|
||||
log.info("finalization={} executed on l1", lastAggregation.intervalString())
|
||||
}
|
||||
@@ -125,13 +125,13 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
|
||||
|
||||
assertBesuAndShomeiRecoveredAsExpected(
|
||||
lastAggregationAndBlobs,
|
||||
timeout = 5.minutes
|
||||
timeout = 5.minutes,
|
||||
)
|
||||
}
|
||||
|
||||
private fun assertBesuAndShomeiRecoveredAsExpected(
|
||||
targetAggregationAndBlobs: AggregationAndBlobs,
|
||||
timeout: Duration
|
||||
timeout: Duration,
|
||||
) {
|
||||
val targetAggregation = targetAggregationAndBlobs.aggregation!!
|
||||
val expectedZkEndStateRootHash = targetAggregationAndBlobs.blobs.last().blobCompressionProof!!.finalStateRootHash
|
||||
@@ -141,7 +141,7 @@ class StateRecoveryWithRealBesuAndStateManagerIntTest {
|
||||
stateManagerClient = stateManagerClient,
|
||||
targetAggregation.endBlockNumber,
|
||||
expectedZkEndStateRootHash,
|
||||
timeout = timeout
|
||||
timeout = timeout,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ class SubmissionsFetchingTaskIntTest {
|
||||
blobsResponsesDir = "$testDataDir/compression/responses",
|
||||
aggregationsResponsesDir = "$testDataDir/aggregation/responses",
|
||||
numberOfAggregations = 7,
|
||||
extraBlobsWithoutAggregation = 0
|
||||
extraBlobsWithoutAggregation = 0,
|
||||
)
|
||||
val rollupDeploymentResult = ContractsManager.get()
|
||||
.deployLineaRollup(numberOfOperators = 2, contractVersion = LineaContractVersion.V6).get()
|
||||
@@ -77,14 +77,14 @@ class SubmissionsFetchingTaskIntTest {
|
||||
l1RpcEndpoint = URI(l1RpcUrl),
|
||||
l1RequestRetryConfig = RetryConfig(backoffDelay = 2.seconds),
|
||||
blobScanEndpoint = URI(blobScanUrl),
|
||||
stateManagerClientEndpoint = URI("http://it-does-not-matter:5432")
|
||||
stateManagerClientEndpoint = URI("http://it-does-not-matter:5432"),
|
||||
)
|
||||
|
||||
contractClientForBlobSubmissions = rollupDeploymentResult.rollupOperatorClient
|
||||
contractClientForAggregationSubmissions = connectToLineaRollupContract(
|
||||
rollupDeploymentResult.contractAddress,
|
||||
rollupDeploymentResult.rollupOperators[1].txManager,
|
||||
smartContractErrors = lineaRollupContractErrors
|
||||
smartContractErrors = lineaRollupContractErrors,
|
||||
)
|
||||
configureLoggers(
|
||||
rootLevel = Level.INFO,
|
||||
@@ -95,7 +95,7 @@ class SubmissionsFetchingTaskIntTest {
|
||||
"linea.plugin.staterecovery.clients" to Level.DEBUG,
|
||||
"test.clients.l1.web3j-default" 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()
|
||||
}
|
||||
@@ -103,18 +103,18 @@ class SubmissionsFetchingTaskIntTest {
|
||||
fun createFetcherTask(
|
||||
l2StartBlockNumber: ULong,
|
||||
debugForceSyncStopBlockNumber: ULong? = null,
|
||||
queuesSizeLimit: Int = 2
|
||||
queuesSizeLimit: Int = 2,
|
||||
): SubmissionsFetchingTask {
|
||||
val l1EventsClient = LineaSubmissionEventsClientImpl(
|
||||
logsSearcher = appClients.ethLogsSearcher,
|
||||
smartContractAddress = appClients.lineaContractClient.contractAddress,
|
||||
l1LatestSearchBlock = BlockParameter.Tag.LATEST,
|
||||
logsBlockChunkSize = 5000
|
||||
logsBlockChunkSize = 5000,
|
||||
)
|
||||
val blobDecompressor: BlobDecompressorAndDeserializer = BlobDecompressorToDomainV1(
|
||||
decompressor = GoNativeBlobDecompressorFactory.getInstance(BlobDecompressorVersion.V1_2_0),
|
||||
staticFields = BlockHeaderStaticFields.localDev,
|
||||
vertx = vertx
|
||||
vertx = vertx,
|
||||
)
|
||||
|
||||
return SubmissionsFetchingTask(
|
||||
@@ -129,14 +129,14 @@ class SubmissionsFetchingTaskIntTest {
|
||||
submissionEventsQueueLimit = queuesSizeLimit,
|
||||
compressedBlobsQueueLimit = queuesSizeLimit,
|
||||
targetDecompressedBlobsQueueLimit = queuesSizeLimit,
|
||||
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber
|
||||
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber,
|
||||
)
|
||||
}
|
||||
|
||||
private fun submitDataToL1ContactAndWaitExecution(
|
||||
aggregationsAndBlobs: List<AggregationAndBlobs> = this.aggregationsAndBlobs,
|
||||
blobChunksSize: Int = 9,
|
||||
waitTimeout: Duration = 4.minutes
|
||||
waitTimeout: Duration = 4.minutes,
|
||||
) {
|
||||
submitBlobsAndAggregationsAndWaitExecution(
|
||||
contractClientForBlobSubmission = contractClientForBlobSubmissions,
|
||||
@@ -146,9 +146,9 @@ class SubmissionsFetchingTaskIntTest {
|
||||
waitTimeout = waitTimeout,
|
||||
l1Web3jClient = createWeb3jHttpClient(
|
||||
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(
|
||||
l2StartBlockNumber = 1UL,
|
||||
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber
|
||||
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber,
|
||||
)
|
||||
}
|
||||
|
||||
private fun assertSubmissionsAreCorrectlyFetched(
|
||||
l2StartBlockNumber: ULong,
|
||||
debugForceSyncStopBlockNumber: ULong? = null
|
||||
debugForceSyncStopBlockNumber: ULong? = null,
|
||||
) {
|
||||
val submissionsFetcher = createFetcherTask(
|
||||
l2StartBlockNumber = l2StartBlockNumber,
|
||||
queuesSizeLimit = 2
|
||||
queuesSizeLimit = 2,
|
||||
)
|
||||
.also { it.start() }
|
||||
val expectedAggregationsAndBlobsToBeFetched =
|
||||
@@ -208,7 +208,7 @@ class SubmissionsFetchingTaskIntTest {
|
||||
?.also { nextSubmission ->
|
||||
fetchedSubmissions.add(nextSubmission)
|
||||
submissionsFetcher.pruneQueueForElementsUpToInclusive(
|
||||
elHeadBlockNumber = nextSubmission.submissionEvents.dataFinalizedEvent.event.endBlockNumber
|
||||
elHeadBlockNumber = nextSubmission.submissionEvents.dataFinalizedEvent.event.endBlockNumber,
|
||||
)
|
||||
}
|
||||
assertThat(submissionsFetcher.finalizationsReadyToImport()).isLessThanOrEqualTo(2)
|
||||
@@ -241,11 +241,11 @@ class SubmissionsFetchingTaskIntTest {
|
||||
|
||||
fun assertFetchedData(
|
||||
fetchedData: SubmissionEventsAndData<BlockFromL1RecoveredData>,
|
||||
sotAggregationData: AggregationAndBlobs
|
||||
sotAggregationData: AggregationAndBlobs,
|
||||
) {
|
||||
assertEventMatchesAggregation(
|
||||
fetchedData.submissionEvents.dataFinalizedEvent.event,
|
||||
sotAggregationData.aggregation!!
|
||||
sotAggregationData.aggregation!!,
|
||||
)
|
||||
assertThat(fetchedData.data.first().header.blockNumber)
|
||||
.isEqualTo(sotAggregationData.blobs.first().startBlockNumber)
|
||||
@@ -255,7 +255,7 @@ class SubmissionsFetchingTaskIntTest {
|
||||
|
||||
fun assertEventMatchesAggregation(
|
||||
event: DataFinalizedV3,
|
||||
aggregation: Aggregation
|
||||
aggregation: Aggregation,
|
||||
) {
|
||||
assertThat(event.startBlockNumber).isEqualTo(aggregation.startBlockNumber)
|
||||
assertThat(event.endBlockNumber).isEqualTo(aggregation.endBlockNumber)
|
||||
|
||||
@@ -12,7 +12,7 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture
|
||||
class FakeExecutionLayerClient(
|
||||
headBlock: BlockNumberAndHash = BlockNumberAndHash(number = 0uL, hash = ByteArray(32) { 0 }),
|
||||
initialStateRecoverStartBlockNumber: ULong? = null,
|
||||
loggerName: String? = null
|
||||
loggerName: String? = null,
|
||||
) : ExecutionLayerClient {
|
||||
private val log = loggerName
|
||||
?.let { LogManager.getLogger(loggerName) }
|
||||
@@ -35,7 +35,7 @@ class FakeExecutionLayerClient(
|
||||
val stateRecoverStatus: StateRecoveryStatus
|
||||
get() = StateRecoveryStatus(
|
||||
headBlockNumber = headBlock.number,
|
||||
stateRecoverStartBlockNumber = stateRecoverStartBlockNumber
|
||||
stateRecoverStartBlockNumber = stateRecoverStartBlockNumber,
|
||||
)
|
||||
|
||||
@Synchronized
|
||||
@@ -46,14 +46,14 @@ class FakeExecutionLayerClient(
|
||||
|
||||
@Synchronized
|
||||
override fun lineaEngineImportBlocksFromBlob(
|
||||
blocks: List<BlockFromL1RecoveredData>
|
||||
blocks: List<BlockFromL1RecoveredData>,
|
||||
): SafeFuture<Unit> {
|
||||
if (log.isTraceEnabled) {
|
||||
log.trace("lineaEngineImportBlocksFromBlob($blocks)")
|
||||
} else {
|
||||
val interval = CommonDomainFunctions.blockIntervalString(
|
||||
blocks.first().header.blockNumber,
|
||||
blocks.last().header.blockNumber
|
||||
blocks.last().header.blockNumber,
|
||||
)
|
||||
log.debug("lineaEngineImportBlocksFromBlob(interval=$interval)")
|
||||
}
|
||||
@@ -64,7 +64,7 @@ class FakeExecutionLayerClient(
|
||||
|
||||
@Synchronized
|
||||
override fun getBlockNumberAndHash(
|
||||
blockParameter: BlockParameter
|
||||
blockParameter: BlockParameter,
|
||||
): SafeFuture<BlockNumberAndHash> {
|
||||
log.trace("getBlockNumberAndHash($blockParameter): $headBlock")
|
||||
return SafeFuture.completedFuture(headBlock)
|
||||
@@ -78,7 +78,7 @@ class FakeExecutionLayerClient(
|
||||
|
||||
@Synchronized
|
||||
override fun lineaEnableStateRecovery(
|
||||
stateRecoverStartBlockNumber: ULong
|
||||
stateRecoverStartBlockNumber: ULong,
|
||||
): SafeFuture<StateRecoveryStatus> {
|
||||
this.stateRecoverStartBlockNumber = stateRecoverStartBlockNumber
|
||||
log.debug("lineaEnableStateRecovery($stateRecoverStartBlockNumber) = $stateRecoverStatus")
|
||||
|
||||
@@ -18,7 +18,7 @@ import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
open class FakeStateManagerClient(
|
||||
_blocksStateRootHashes: Map<ULong, ByteArray> = emptyMap(),
|
||||
var headBlockNumber: ULong = _blocksStateRootHashes.keys.maxOrNull() ?: 0UL
|
||||
var headBlockNumber: ULong = _blocksStateRootHashes.keys.maxOrNull() ?: 0UL,
|
||||
) : StateManagerClientV1 {
|
||||
open val blocksStateRootHashes: MutableMap<ULong, ByteArray> =
|
||||
ConcurrentHashMap<ULong, ByteArray>(_blocksStateRootHashes)
|
||||
@@ -33,8 +33,8 @@ open class FakeStateManagerClient(
|
||||
?.let { SafeFuture.completedFuture(it) }
|
||||
?: SafeFuture.failedFuture(
|
||||
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(
|
||||
blockInterval: BlockInterval
|
||||
blockInterval: BlockInterval,
|
||||
): SafeFuture<Result<GetZkEVMStateMerkleProofResponse, ErrorResponse<StateManagerErrorType>>> {
|
||||
// For state recovery, we just need the endStateRootHash
|
||||
return getStateRootHash(blockInterval.endBlockNumber)
|
||||
@@ -53,26 +53,26 @@ open class FakeStateManagerClient(
|
||||
zkStateMerkleProof = ArrayNode(null),
|
||||
zkParentStateRootHash = ByteArray(32),
|
||||
zkEndStateRootHash = stateRootHash,
|
||||
zkStateManagerVersion = "fake-version"
|
||||
)
|
||||
zkStateManagerVersion = "fake-version",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FakeStateManagerClientBasedOnBlobsRecords(
|
||||
val blobRecords: List<BlobRecord>
|
||||
val blobRecords: List<BlobRecord>,
|
||||
) : FakeStateManagerClient(
|
||||
_blocksStateRootHashes = blobRecords
|
||||
.associate { it.endBlockNumber to it.blobCompressionProof!!.finalStateRootHash }
|
||||
.associate { it.endBlockNumber to it.blobCompressionProof!!.finalStateRootHash },
|
||||
)
|
||||
|
||||
class FakeStateManagerClientReadFromL1(
|
||||
headBlockNumber: ULong,
|
||||
val logsSearcher: EthLogsSearcher,
|
||||
val contractAddress: String
|
||||
val contractAddress: String,
|
||||
) : FakeStateManagerClient(
|
||||
headBlockNumber = headBlockNumber
|
||||
headBlockNumber = headBlockNumber,
|
||||
) {
|
||||
|
||||
override fun getStateRootHash(blockNumber: ULong): SafeFuture<ByteArray> {
|
||||
@@ -87,8 +87,8 @@ class FakeStateManagerClientReadFromL1(
|
||||
topics = listOf(
|
||||
DataFinalizedV3.topic,
|
||||
null,
|
||||
blockNumber.toHexStringUInt256()
|
||||
)
|
||||
blockNumber.toHexStringUInt256(),
|
||||
),
|
||||
).thenApply { logs ->
|
||||
logs.firstOrNull()?.let { finalizationLog ->
|
||||
DataFinalizedV3.fromEthLog(finalizationLog).event.finalStateRootHash
|
||||
|
||||
@@ -34,7 +34,7 @@ open class TestRunner(
|
||||
private val l1RpcUrl: String,
|
||||
private val blobScanUrl: String,
|
||||
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")
|
||||
val appConfig = StateRecoveryApp.Config(
|
||||
@@ -45,7 +45,7 @@ open class TestRunner(
|
||||
executionClientPollingInterval = 1.seconds,
|
||||
smartContractAddress = smartContractAddress,
|
||||
l1getLogsChunkSize = 10_000u,
|
||||
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber
|
||||
debugForceSyncStopBlockNumber = debugForceSyncStopBlockNumber,
|
||||
)
|
||||
val appClients = createAppClients(
|
||||
vertx = vertx,
|
||||
@@ -56,17 +56,17 @@ open class TestRunner(
|
||||
blobScanEndpoint = URI(blobScanUrl),
|
||||
blobScanRequestRetryConfig = RetryConfig(backoffDelay = 10.milliseconds, timeout = 2.minutes),
|
||||
blobscanRequestRateLimitBackoffDelay = blobScanRatelimitBackoffDelay,
|
||||
stateManagerClientEndpoint = URI("http://it-does-not-matter:5432")
|
||||
stateManagerClientEndpoint = URI("http://it-does-not-matter:5432"),
|
||||
)
|
||||
private val fakeExecutionLayerClient = FakeExecutionLayerClient(
|
||||
headBlock = BlockNumberAndHash(number = l2RecoveryStartBlockNumber - 1UL, hash = ByteArray(32) { 0 }),
|
||||
initialStateRecoverStartBlockNumber = l2RecoveryStartBlockNumber,
|
||||
loggerName = "test.fake.clients.execution-layer"
|
||||
loggerName = "test.fake.clients.execution-layer",
|
||||
)
|
||||
var fakeStateManagerClient: StateManagerClientV1 = FakeStateManagerClientReadFromL1(
|
||||
headBlockNumber = ULong.MAX_VALUE,
|
||||
logsSearcher = appClients.ethLogsSearcher,
|
||||
contractAddress = StateRecoveryApp.Config.lineaSepolia.smartContractAddress
|
||||
contractAddress = StateRecoveryApp.Config.lineaSepolia.smartContractAddress,
|
||||
)
|
||||
var stateRecoverApp: StateRecoveryApp = StateRecoveryApp(
|
||||
vertx = vertx,
|
||||
@@ -77,7 +77,7 @@ open class TestRunner(
|
||||
transactionDetailsClient = appClients.transactionDetailsClient,
|
||||
blockHeaderStaticFields = BlockHeaderStaticFields.localDev,
|
||||
lineaContractClient = appClients.lineaContractClient,
|
||||
config = appConfig
|
||||
config = appConfig,
|
||||
)
|
||||
|
||||
init {
|
||||
@@ -86,12 +86,12 @@ open class TestRunner(
|
||||
"linea.staterecovery" to Level.TRACE,
|
||||
"linea.plugin.staterecovery" to Level.INFO,
|
||||
"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(
|
||||
timeout: kotlin.time.Duration = 10.minutes
|
||||
timeout: kotlin.time.Duration = 10.minutes,
|
||||
) {
|
||||
log.info("Running test case")
|
||||
stateRecoverApp.start().get()
|
||||
@@ -113,7 +113,7 @@ fun main() {
|
||||
l2RecoveryStartBlockNumber = 18_504_528UL,
|
||||
l1RpcUrl = "https://mainnet.infura.io/v3/$infuraAppKey",
|
||||
blobScanUrl = "https://api.blobscan.com/",
|
||||
blobScanRatelimitBackoffDelay = 1.seconds
|
||||
blobScanRatelimitBackoffDelay = 1.seconds,
|
||||
)
|
||||
// val sepoliaTestRunner = TestRunner(
|
||||
// l1RpcUrl = "https://sepolia.infura.io/v3/$infuraAppKey",
|
||||
|
||||
@@ -19,7 +19,7 @@ import kotlin.time.toJavaDuration
|
||||
fun execCommandAndAssertSuccess(
|
||||
command: String,
|
||||
timeout: Duration = 1.minutes,
|
||||
log: Logger
|
||||
log: Logger,
|
||||
): SafeFuture<CommandResult> {
|
||||
return Runner
|
||||
.executeCommandFailOnNonZeroExitCode(command, timeout = timeout, log = log)
|
||||
@@ -35,7 +35,7 @@ fun assertBesuAndShomeiRecoveredAsExpected(
|
||||
stateManagerClient: StateManagerClientV1,
|
||||
expectedBlockNumber: ULong,
|
||||
expectedZkEndStateRootHash: ByteArray,
|
||||
timeout: Duration = 60.seconds
|
||||
timeout: Duration = 60.seconds,
|
||||
) {
|
||||
await()
|
||||
.pollInterval(1.seconds.toJavaDuration())
|
||||
@@ -53,7 +53,7 @@ fun waitExecutionLayerToBeUpAndRunning(
|
||||
executionLayerUrl: String,
|
||||
expectedHeadBlockNumber: ULong = 0UL,
|
||||
log: Logger,
|
||||
timeout: Duration = 2.minutes
|
||||
timeout: Duration = 2.minutes,
|
||||
) {
|
||||
val web3jElClient = createWeb3jHttpClient(executionLayerUrl)
|
||||
await()
|
||||
|
||||
@@ -7,7 +7,7 @@ import linea.staterecovery.DataFinalizedV3
|
||||
|
||||
fun getLastFinalizationOnL1(
|
||||
logsSearcher: EthLogsSearcherImpl,
|
||||
contractAddress: String
|
||||
contractAddress: String,
|
||||
): EthLogEvent<DataFinalizedV3> {
|
||||
return getFinalizationsOnL1(logsSearcher, contractAddress)
|
||||
.lastOrNull()
|
||||
@@ -16,12 +16,12 @@ fun getLastFinalizationOnL1(
|
||||
|
||||
fun getFinalizationsOnL1(
|
||||
logsSearcher: EthLogsSearcherImpl,
|
||||
contractAddress: String
|
||||
contractAddress: String,
|
||||
): List<EthLogEvent<DataFinalizedV3>> {
|
||||
return logsSearcher.getLogs(
|
||||
fromBlock = BlockParameter.Tag.EARLIEST,
|
||||
toBlock = BlockParameter.Tag.LATEST,
|
||||
address = contractAddress,
|
||||
topics = listOf(DataFinalizedV3.topic)
|
||||
topics = listOf(DataFinalizedV3.topic),
|
||||
).get().map(DataFinalizedV3.Companion::fromEthLog)
|
||||
}
|
||||
|
||||
17
build.gradle
17
build.gradle
@@ -118,18 +118,13 @@ allprojects {
|
||||
indentWithSpaces(2)
|
||||
endWithNewline()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO in later ticket - apply these linting rules to all monorepo projects
|
||||
if (subproject.path.startsWith(':besu-plugins:linea-sequencer')) {
|
||||
subproject.spotless {
|
||||
java {
|
||||
target 'src/**/*.java'
|
||||
targetExclude '**/src/test/java/**ReferenceTest**', '**/src/main/generated/**', '**/src/test/generated/**', '**/src/jmh/generated/**'
|
||||
removeUnusedImports()
|
||||
trimTrailingWhitespace()
|
||||
endWithNewline()
|
||||
}
|
||||
java {
|
||||
target 'src/**/*.java'
|
||||
targetExclude '**/src/test/java/**ReferenceTest**', '**/src/main/generated/**', '**/src/test/generated/**', '**/src/jmh/generated/**'
|
||||
removeUnusedImports()
|
||||
trimTrailingWhitespace()
|
||||
endWithNewline()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.apache.logging.log4j.Logger
|
||||
import java.nio.file.Path
|
||||
|
||||
inline fun <reified T : Any> loadConfigsOrError(
|
||||
configFiles: List<Path>
|
||||
configFiles: List<Path>,
|
||||
): Result<T, String> {
|
||||
val confBuilder: ConfigLoaderBuilder = ConfigLoaderBuilder.Companion
|
||||
.empty()
|
||||
@@ -43,7 +43,7 @@ fun logErrorIfPresent(
|
||||
configName: String,
|
||||
configFiles: List<Path>,
|
||||
configLoadingResult: Result<Any?, String>,
|
||||
logger: Logger
|
||||
logger: Logger,
|
||||
) {
|
||||
if (configLoadingResult is Err) {
|
||||
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(
|
||||
configFiles: List<Path>,
|
||||
configName: String,
|
||||
logger: Logger = LogManager.getLogger("linea.coordinator.config")
|
||||
logger: Logger = LogManager.getLogger("linea.coordinator.config"),
|
||||
): Result<T, String> {
|
||||
return loadConfigsOrError<T>(configFiles)
|
||||
.also { logErrorIfPresent(configName, configFiles, it, logger) }
|
||||
@@ -64,7 +64,7 @@ fun loadConfigsOrError(
|
||||
tracesLimitsFileV2: Path,
|
||||
gasPriceCapTimeOfDayMultipliersFile: Path,
|
||||
smartContractErrorsFile: Path,
|
||||
logger: Logger = LogManager.getLogger("linea.coordinator.config")
|
||||
logger: Logger = LogManager.getLogger("linea.coordinator.config"),
|
||||
): Result<CoordinatorConfigTomlDto, String> {
|
||||
val coordinatorBaseConfigs =
|
||||
loadConfigsAndLogErrors<CoordinatorConfigTomlDto>(coordinatorConfigFiles, "coordinator", logger)
|
||||
@@ -74,18 +74,18 @@ fun loadConfigsOrError(
|
||||
loadConfigsAndLogErrors<GasPriceCapTimeOfDayMultipliersConfig>(
|
||||
listOf(gasPriceCapTimeOfDayMultipliersFile),
|
||||
"l1 submission gas prices caps",
|
||||
logger
|
||||
logger,
|
||||
)
|
||||
val smartContractErrorsConfig = loadConfigsAndLogErrors<SmartContractErrorCodesConfig>(
|
||||
listOf(smartContractErrorsFile),
|
||||
"smart contract errors",
|
||||
logger
|
||||
logger,
|
||||
)
|
||||
val configError = listOf(
|
||||
coordinatorBaseConfigs,
|
||||
tracesLimitsV2Configs,
|
||||
gasPriceCapTimeOfDayMultipliersConfig,
|
||||
smartContractErrorsConfig
|
||||
smartContractErrorsConfig,
|
||||
)
|
||||
.find { it is Err }
|
||||
|
||||
@@ -98,13 +98,13 @@ fun loadConfigsOrError(
|
||||
val finalConfig = baseConfig.copy(
|
||||
conflation = baseConfig.conflation.copy(
|
||||
_tracesLimitsV2 = tracesLimitsV2Configs.get()?.tracesLimits?.let { TracesCountersV2(it) },
|
||||
_smartContractErrors = smartContractErrorsConfig.get()!!.smartContractErrors
|
||||
_smartContractErrors = smartContractErrorsConfig.get()!!.smartContractErrors,
|
||||
),
|
||||
l1DynamicGasPriceCapService = baseConfig.l1DynamicGasPriceCapService.copy(
|
||||
gasPriceCapCalculation = baseConfig.l1DynamicGasPriceCapService.gasPriceCapCalculation.copy(
|
||||
timeOfDayMultipliers = gasPriceCapTimeOfDayMultipliersConfig.get()?.gasPriceCapTimeOfDayMultipliers
|
||||
)
|
||||
)
|
||||
timeOfDayMultipliers = gasPriceCapTimeOfDayMultipliersConfig.get()?.gasPriceCapTimeOfDayMultipliers,
|
||||
),
|
||||
),
|
||||
)
|
||||
return Ok(finalConfig)
|
||||
}
|
||||
@@ -114,14 +114,14 @@ fun loadConfigs(
|
||||
tracesLimitsFileV2: Path,
|
||||
gasPriceCapTimeOfDayMultipliersFile: Path,
|
||||
smartContractErrorsFile: Path,
|
||||
logger: Logger = LogManager.getLogger("linea.coordinator.config")
|
||||
logger: Logger = LogManager.getLogger("linea.coordinator.config"),
|
||||
): CoordinatorConfig {
|
||||
loadConfigsOrError(
|
||||
coordinatorConfigFiles,
|
||||
tracesLimitsFileV2,
|
||||
gasPriceCapTimeOfDayMultipliersFile,
|
||||
smartContractErrorsFile,
|
||||
logger
|
||||
logger,
|
||||
).let {
|
||||
return it
|
||||
.getOrElse {
|
||||
|
||||
@@ -6,10 +6,10 @@ import net.consensys.linea.vertx.ObservabilityServer
|
||||
|
||||
class Api(
|
||||
private val configs: Config,
|
||||
private val vertx: Vertx
|
||||
private val vertx: Vertx,
|
||||
) {
|
||||
data class Config(
|
||||
val observabilityPort: UInt
|
||||
val observabilityPort: UInt,
|
||||
)
|
||||
|
||||
private var observabilityServerId: String? = null
|
||||
|
||||
@@ -23,7 +23,7 @@ import java.net.URI
|
||||
fun createTransactionManager(
|
||||
vertx: Vertx,
|
||||
signerConfig: SignerConfig,
|
||||
client: Web3j
|
||||
client: Web3j,
|
||||
): AsyncFriendlyTransactionManager {
|
||||
val transactionSignService = when (signerConfig.type) {
|
||||
SignerConfig.Type.Web3j -> {
|
||||
@@ -57,7 +57,7 @@ fun createLineaRollupContractClient(
|
||||
contractGasProvider: ContractGasProvider,
|
||||
web3jClient: Web3j,
|
||||
smartContractErrors: SmartContractErrors,
|
||||
useEthEstimateGas: Boolean
|
||||
useEthEstimateGas: Boolean,
|
||||
): LineaRollupSmartContractClient {
|
||||
return Web3JLineaRollupSmartContractClient.load(
|
||||
contractAddress = l1Config.zkEvmContractAddress,
|
||||
@@ -65,6 +65,6 @@ fun createLineaRollupContractClient(
|
||||
transactionManager = transactionManager,
|
||||
contractGasProvider = contractGasProvider,
|
||||
smartContractErrors = smartContractErrors,
|
||||
useEthEstimateGas = useEthEstimateGas
|
||||
useEthEstimateGas = useEthEstimateGas,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -51,20 +51,20 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
|
||||
vertx = vertx,
|
||||
metricsFacade = MicrometerMetricsFacade(meterRegistry),
|
||||
requestResponseLogLevel = Level.TRACE,
|
||||
failuresLogLevel = Level.WARN
|
||||
failuresLogLevel = Level.WARN,
|
||||
)
|
||||
private val api = Api(
|
||||
Api.Config(
|
||||
configs.api.observabilityPort
|
||||
configs.api.observabilityPort,
|
||||
),
|
||||
vertx
|
||||
vertx,
|
||||
)
|
||||
private val l2Web3jClient: Web3j = createWeb3jHttpClient(
|
||||
rpcUrl = configs.l2.rpcEndpoint.toString(),
|
||||
log = LogManager.getLogger("clients.l2.eth-api.rpc-node"),
|
||||
pollingInterval = 1.seconds,
|
||||
requestResponseLogLevel = Level.TRACE,
|
||||
failuresLogLevel = Level.DEBUG
|
||||
failuresLogLevel = Level.DEBUG,
|
||||
)
|
||||
|
||||
private val persistenceRetryer = PersistenceRetryer(
|
||||
@@ -72,8 +72,8 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
|
||||
config = PersistenceRetryer.Config(
|
||||
backoffDelay = configs.persistenceRetry.backoffDelay.toKotlinDuration(),
|
||||
maxRetries = configs.persistenceRetry.maxRetries,
|
||||
timeout = configs.persistenceRetry.timeout?.toKotlinDuration()
|
||||
)
|
||||
timeout = configs.persistenceRetry.timeout?.toKotlinDuration(),
|
||||
),
|
||||
)
|
||||
|
||||
private val sqlClient: SqlClient = initDb(configs.database)
|
||||
@@ -81,10 +81,10 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
|
||||
PostgresBatchesRepository(
|
||||
batchesDao = RetryingBatchesPostgresDao(
|
||||
delegate = BatchesPostgresDao(
|
||||
connection = sqlClient
|
||||
connection = sqlClient,
|
||||
),
|
||||
persistenceRetryer = persistenceRetryer
|
||||
)
|
||||
persistenceRetryer = persistenceRetryer,
|
||||
),
|
||||
)
|
||||
|
||||
private val blobsRepository =
|
||||
@@ -92,21 +92,21 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
|
||||
blobsDao = RetryingBlobsPostgresDao(
|
||||
delegate = BlobsPostgresDao(
|
||||
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(
|
||||
aggregationsPostgresDao = RetryingPostgresAggregationsDao(
|
||||
delegate = PostgresAggregationsDao(
|
||||
connection = sqlClient
|
||||
connection = sqlClient,
|
||||
),
|
||||
persistenceRetryer = persistenceRetryer
|
||||
)
|
||||
persistenceRetryer = persistenceRetryer,
|
||||
),
|
||||
)
|
||||
|
||||
private val l1FeeHistoriesRepository =
|
||||
@@ -116,11 +116,11 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
|
||||
minBaseFeePerBlobGasToCache =
|
||||
configs.l1DynamicGasPriceCapService.gasPriceCapCalculation.historicBaseFeePerBlobGasLowerBound,
|
||||
fixedAverageRewardToCache =
|
||||
configs.l1DynamicGasPriceCapService.gasPriceCapCalculation.historicAvgRewardConstant
|
||||
configs.l1DynamicGasPriceCapService.gasPriceCapCalculation.historicAvgRewardConstant,
|
||||
),
|
||||
FeeHistoriesPostgresDao(
|
||||
sqlClient
|
||||
)
|
||||
sqlClient,
|
||||
),
|
||||
)
|
||||
|
||||
private val l1App = L1DependentApp(
|
||||
@@ -133,7 +133,7 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
|
||||
aggregationsRepository = aggregationsRepository,
|
||||
l1FeeHistoriesRepository = l1FeeHistoriesRepository,
|
||||
smartContractErrors = configs.conflation.smartContractErrors,
|
||||
metricsFacade = micrometerMetricsFacade
|
||||
metricsFacade = micrometerMetricsFacade,
|
||||
)
|
||||
|
||||
private val requestFileCleanup = DirectoryCleaner(
|
||||
@@ -144,7 +144,7 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
|
||||
configs.proversConfig.proverA.proofAggregation.requestsDirectory,
|
||||
configs.proversConfig.proverB?.execution?.requestsDirectory,
|
||||
configs.proversConfig.proverB?.blobCompression?.requestsDirectory,
|
||||
configs.proversConfig.proverB?.proofAggregation?.requestsDirectory
|
||||
configs.proversConfig.proverB?.proofAggregation?.requestsDirectory,
|
||||
),
|
||||
fileFilters = DirectoryCleaner.getSuffixFileFilters(
|
||||
listOfNotNull(
|
||||
@@ -153,9 +153,9 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
|
||||
configs.proversConfig.proverA.proofAggregation.inprogressRequestWritingSuffix,
|
||||
configs.proversConfig.proverB?.execution?.inprogressRequestWritingSuffix,
|
||||
configs.proversConfig.proverB?.blobCompression?.inprogressRequestWritingSuffix,
|
||||
configs.proversConfig.proverB?.proofAggregation?.inprogressRequestWritingSuffix
|
||||
)
|
||||
) + DirectoryCleaner.JSON_FILE_FILTER
|
||||
configs.proversConfig.proverB?.proofAggregation?.inprogressRequestWritingSuffix,
|
||||
),
|
||||
) + DirectoryCleaner.JSON_FILE_FILTER,
|
||||
)
|
||||
|
||||
init {
|
||||
@@ -176,7 +176,7 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
|
||||
SafeFuture.allOf(
|
||||
l1App.stop(),
|
||||
SafeFuture.fromRunnable { l2Web3jClient.shutdown() },
|
||||
api.stop().toSafeFuture()
|
||||
api.stop().toSafeFuture(),
|
||||
).thenApply {
|
||||
LoadBalancingJsonRpcClient.stop()
|
||||
}.thenCompose {
|
||||
@@ -201,7 +201,7 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
|
||||
database = dbConfig.schema,
|
||||
target = dbVersion,
|
||||
username = dbConfig.username,
|
||||
password = dbConfig.password.value
|
||||
password = dbConfig.password.value,
|
||||
)
|
||||
return Db.vertxSqlClient(
|
||||
vertx = vertx,
|
||||
@@ -211,7 +211,7 @@ class CoordinatorApp(private val configs: CoordinatorConfig) {
|
||||
username = dbConfig.username,
|
||||
password = dbConfig.password.value,
|
||||
maxPoolSize = dbConfig.transactionalPoolSize,
|
||||
pipeliningLimit = dbConfig.readPipeliningLimit
|
||||
pipeliningLimit = dbConfig.readPipeliningLimit,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.util.concurrent.Callable
|
||||
synopsisHeading = "%n",
|
||||
descriptionHeading = "%nDescription:%n%n",
|
||||
optionListHeading = "%nOptions:%n",
|
||||
footerHeading = "%n"
|
||||
footerHeading = "%n",
|
||||
)
|
||||
class CoordinatorAppCli
|
||||
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"],
|
||||
paramLabel = "<FILE>",
|
||||
description = ["Prover traces limits for linea besu"],
|
||||
arity = "1"
|
||||
arity = "1",
|
||||
)
|
||||
private val tracesLimitsV2File: File? = null
|
||||
|
||||
@@ -40,27 +40,24 @@ internal constructor(private val errorWriter: PrintWriter, private val startActi
|
||||
names = ["--smart-contract-errors"],
|
||||
paramLabel = "<FILE>",
|
||||
description = ["Smart contract error codes"],
|
||||
arity = "1"
|
||||
arity = "1",
|
||||
)
|
||||
|
||||
private val smartContractErrorsFile: File? = null
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--gas-price-cap-time-of-day-multipliers"],
|
||||
paramLabel = "<FILE>",
|
||||
description = ["Time-of-day multipliers for calculation of L1 dynamic gas price caps"],
|
||||
arity = "1"
|
||||
arity = "1",
|
||||
)
|
||||
|
||||
private val gasPriceCapTimeOfDayMultipliersFile: File? = null
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--check-configs-only"],
|
||||
paramLabel = "<BOOLEAN>",
|
||||
description = ["Validates configuration files only, without starting the application."],
|
||||
arity = "0..1"
|
||||
arity = "0..1",
|
||||
)
|
||||
|
||||
private var checkConfigsOnly: Boolean = false
|
||||
|
||||
override fun call(): Int {
|
||||
@@ -97,7 +94,7 @@ internal constructor(private val errorWriter: PrintWriter, private val startActi
|
||||
tracesLimitsFileV2 = tracesLimitsV2File.toPath(),
|
||||
smartContractErrorsFile = smartContractErrorsFile.toPath(),
|
||||
gasPriceCapTimeOfDayMultipliersFile = gasPriceCapTimeOfDayMultipliersFile.toPath(),
|
||||
logger = logger
|
||||
logger = logger,
|
||||
)
|
||||
|
||||
if (checkConfigsOnly) {
|
||||
|
||||
@@ -39,7 +39,7 @@ class CoordinatorAppMain {
|
||||
// Messages in App.stop won't appear in the logs
|
||||
Configurator.shutdown(LogManager.getContext() as LoggerContext)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
app.start()
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ class L1DependentApp(
|
||||
private val aggregationsRepository: AggregationsRepository,
|
||||
l1FeeHistoriesRepository: FeeHistoriesRepositoryWithCache,
|
||||
private val smartContractErrors: SmartContractErrors,
|
||||
private val metricsFacade: MetricsFacade
|
||||
private val metricsFacade: MetricsFacade,
|
||||
) : LongRunningService {
|
||||
private val log = LogManager.getLogger(this::class.java)
|
||||
|
||||
@@ -132,13 +132,13 @@ class L1DependentApp(
|
||||
private val l2TransactionManager = createTransactionManager(
|
||||
vertx,
|
||||
configs.l2Signer,
|
||||
l2Web3jClient
|
||||
l2Web3jClient,
|
||||
)
|
||||
|
||||
private val l1Web3jClient = createWeb3jHttpClient(
|
||||
rpcUrl = configs.l1.rpcEndpoint.toString(),
|
||||
log = LogManager.getLogger("clients.l1.eth-api"),
|
||||
pollingInterval = 1.seconds
|
||||
pollingInterval = 1.seconds,
|
||||
)
|
||||
private val l1Web3jService = Web3jBlobExtended(HttpService(configs.l1.ethFeeHistoryEndpoint.toString()))
|
||||
|
||||
@@ -147,7 +147,7 @@ class L1DependentApp(
|
||||
private val proverClientFactory = ProverClientFactory(
|
||||
vertx = vertx,
|
||||
config = configs.proversConfig,
|
||||
metricsFacade = metricsFacade
|
||||
metricsFacade = metricsFacade,
|
||||
)
|
||||
|
||||
private val l2ExtendedWeb3j = ExtendedWeb3JImpl(l2Web3jClient)
|
||||
@@ -155,32 +155,32 @@ class L1DependentApp(
|
||||
private val finalizationTransactionManager = createTransactionManager(
|
||||
vertx,
|
||||
configs.finalizationSigner,
|
||||
l1Web3jClient
|
||||
l1Web3jClient,
|
||||
)
|
||||
|
||||
private val l1MinPriorityFeeCalculator: FeesCalculator = WMAFeesCalculator(
|
||||
WMAFeesCalculator.Config(
|
||||
baseFeeCoefficient = 0.0,
|
||||
priorityFeeWmaCoefficient = 1.0
|
||||
)
|
||||
priorityFeeWmaCoefficient = 1.0,
|
||||
),
|
||||
)
|
||||
|
||||
private val l1DataSubmissionPriorityFeeCalculator: FeesCalculator = BoundableFeeCalculator(
|
||||
BoundableFeeCalculator.Config(
|
||||
feeUpperBound = configs.blobSubmission.priorityFeePerGasUpperBound.toDouble(),
|
||||
feeLowerBound = configs.blobSubmission.priorityFeePerGasLowerBound.toDouble(),
|
||||
feeMargin = 0.0
|
||||
feeMargin = 0.0,
|
||||
),
|
||||
l1MinPriorityFeeCalculator
|
||||
l1MinPriorityFeeCalculator,
|
||||
)
|
||||
|
||||
private val l1FinalizationPriorityFeeCalculator: FeesCalculator = BoundableFeeCalculator(
|
||||
BoundableFeeCalculator.Config(
|
||||
feeUpperBound = configs.l1.maxPriorityFeePerGasCap.toDouble() * configs.l1.gasPriceCapMultiplierForFinalization,
|
||||
feeLowerBound = 0.0,
|
||||
feeMargin = 0.0
|
||||
feeMargin = 0.0,
|
||||
),
|
||||
l1MinPriorityFeeCalculator
|
||||
l1MinPriorityFeeCalculator,
|
||||
)
|
||||
|
||||
private val feesFetcher: FeesFetcher = FeeHistoryFetcherImpl(
|
||||
@@ -188,13 +188,13 @@ class L1DependentApp(
|
||||
l1Web3jService,
|
||||
FeeHistoryFetcherImpl.Config(
|
||||
configs.l1.feeHistoryBlockCount.toUInt(),
|
||||
configs.l1.feeHistoryRewardPercentile
|
||||
)
|
||||
configs.l1.feeHistoryRewardPercentile,
|
||||
),
|
||||
)
|
||||
|
||||
private val lineaRollupClient: LineaRollupSmartContractClientReadOnly = Web3JLineaRollupSmartContractClientReadOnly(
|
||||
contractAddress = configs.l1.zkEvmContractAddress,
|
||||
web3j = l1Web3jClient
|
||||
web3j = l1Web3jClient,
|
||||
)
|
||||
|
||||
private val l1FinalizationMonitor = run {
|
||||
@@ -202,11 +202,11 @@ class L1DependentApp(
|
||||
config =
|
||||
FinalizationMonitorImpl.Config(
|
||||
pollingInterval = configs.l1.finalizationPollingInterval.toKotlinDuration(),
|
||||
l1QueryBlockTag = configs.l1.l1QueryBlockTag
|
||||
l1QueryBlockTag = configs.l1.l1QueryBlockTag,
|
||||
),
|
||||
contract = lineaRollupClient,
|
||||
l2Client = l2Web3jClient,
|
||||
vertx = vertx
|
||||
vertx = vertx,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ class L1DependentApp(
|
||||
httpJsonRpcClientFactory = httpJsonRpcClientFactory,
|
||||
lineaRollupClient = lineaRollupClient,
|
||||
l2Web3jClient = l2Web3jClient,
|
||||
vertx = vertx
|
||||
vertx = vertx,
|
||||
)
|
||||
|
||||
private val gasPriceCapProvider =
|
||||
@@ -246,11 +246,11 @@ class L1DependentApp(
|
||||
finalizationTargetMaxDelay =
|
||||
configs.l1DynamicGasPriceCapService.gasPriceCapCalculation.finalizationTargetMaxDelay.toKotlinDuration(),
|
||||
gasPriceCapsCoefficient =
|
||||
configs.l1DynamicGasPriceCapService.gasPriceCapCalculation.gasPriceCapsCheckCoefficient
|
||||
configs.l1DynamicGasPriceCapService.gasPriceCapCalculation.gasPriceCapsCheckCoefficient,
|
||||
),
|
||||
l2ExtendedWeb3JClient = l2ExtendedWeb3j,
|
||||
feeHistoriesRepository = l1FeeHistoriesRepository,
|
||||
gasPriceCapCalculator = l1GasPriceCapCalculator
|
||||
gasPriceCapCalculator = l1GasPriceCapCalculator,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
@@ -261,10 +261,10 @@ class L1DependentApp(
|
||||
config = GasPriceCapProviderForDataSubmission.Config(
|
||||
maxPriorityFeePerGasCap = configs.l1.maxPriorityFeePerGasCap,
|
||||
maxFeePerGasCap = configs.l1.maxFeePerGasCap,
|
||||
maxFeePerBlobGasCap = configs.l1.maxFeePerBlobGasCap
|
||||
maxFeePerBlobGasCap = configs.l1.maxFeePerBlobGasCap,
|
||||
),
|
||||
gasPriceCapProvider = gasPriceCapProvider!!,
|
||||
metricsFacade = metricsFacade
|
||||
metricsFacade = metricsFacade,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
@@ -275,10 +275,10 @@ class L1DependentApp(
|
||||
config = GasPriceCapProviderForFinalization.Config(
|
||||
maxPriorityFeePerGasCap = configs.l1.maxPriorityFeePerGasCap,
|
||||
maxFeePerGasCap = configs.l1.maxFeePerGasCap,
|
||||
gasPriceCapMultiplier = configs.l1.gasPriceCapMultiplierForFinalization
|
||||
gasPriceCapMultiplier = configs.l1.gasPriceCapMultiplierForFinalization,
|
||||
),
|
||||
gasPriceCapProvider = gasPriceCapProvider!!,
|
||||
metricsFacade = metricsFacade
|
||||
metricsFacade = metricsFacade,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
@@ -287,11 +287,11 @@ class L1DependentApp(
|
||||
private val lastFinalizedBlock = lastFinalizedBlock().get()
|
||||
private val lastProcessedBlockNumber = resumeConflationFrom(
|
||||
aggregationsRepository,
|
||||
lastFinalizedBlock
|
||||
lastFinalizedBlock,
|
||||
).get()
|
||||
private val lastConsecutiveAggregatedBlockNumber = resumeAggregationFrom(
|
||||
aggregationsRepository,
|
||||
lastFinalizedBlock
|
||||
lastFinalizedBlock,
|
||||
).get()
|
||||
|
||||
private fun createDeadlineConflationCalculatorRunner(): DeadlineConflationCalculatorRunner {
|
||||
@@ -301,15 +301,15 @@ class L1DependentApp(
|
||||
config = ConflationCalculatorByTimeDeadline.Config(
|
||||
conflationDeadline = configs.conflation.conflationDeadline.toKotlinDuration(),
|
||||
conflationDeadlineLastBlockConfirmationDelay =
|
||||
configs.conflation.conflationDeadlineLastBlockConfirmationDelay.toKotlinDuration()
|
||||
configs.conflation.conflationDeadlineLastBlockConfirmationDelay.toKotlinDuration(),
|
||||
),
|
||||
lastBlockNumber = lastProcessedBlockNumber,
|
||||
clock = Clock.System,
|
||||
latestBlockProvider = GethCliqueSafeBlockProvider(
|
||||
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) {
|
||||
calculators.add(
|
||||
ConflationCalculatorByBlockLimit(
|
||||
blockLimit = configs.conflation.blocksLimit.toUInt()
|
||||
)
|
||||
blockLimit = configs.conflation.blocksLimit.toUInt(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -330,15 +330,15 @@ class L1DependentApp(
|
||||
if (configs.conflation.conflationTargetEndBlockNumbers.isNotEmpty()) {
|
||||
calculators.add(
|
||||
ConflationCalculatorByTargetBlockNumbers(
|
||||
targetEndBlockNumbers = configs.conflation.conflationTargetEndBlockNumbers
|
||||
)
|
||||
targetEndBlockNumbers = configs.conflation.conflationTargetEndBlockNumbers,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createCalculatorsForBlobsAndConflation(
|
||||
logger: Logger,
|
||||
compressedBlobCalculator: ConflationCalculatorByDataCompressed
|
||||
compressedBlobCalculator: ConflationCalculatorByDataCompressed,
|
||||
): List<ConflationCalculator> {
|
||||
val calculators: MutableList<ConflationCalculator> =
|
||||
mutableListOf(
|
||||
@@ -346,9 +346,9 @@ class L1DependentApp(
|
||||
tracesCountersLimit = configs.conflation.tracesLimitsV2,
|
||||
emptyTracesCounters = TracesCountersV2.EMPTY_TRACES_COUNT,
|
||||
metricsFacade = metricsFacade,
|
||||
log = logger
|
||||
log = logger,
|
||||
),
|
||||
compressedBlobCalculator
|
||||
compressedBlobCalculator,
|
||||
)
|
||||
addBlocksLimitCalculatorIfDefined(calculators)
|
||||
addTargetEndBlockConflationCalculatorIfDefined(calculators)
|
||||
@@ -363,18 +363,18 @@ class L1DependentApp(
|
||||
val blobCompressor = GoBackedBlobCompressor.getInstance(
|
||||
compressorVersion = compressorVersion,
|
||||
dataLimit = configs.blobCompression.blobSizeLimit.toUInt(),
|
||||
metricsFacade = metricsFacade
|
||||
metricsFacade = metricsFacade,
|
||||
)
|
||||
|
||||
val compressedBlobCalculator = ConflationCalculatorByDataCompressed(
|
||||
blobCompressor = blobCompressor
|
||||
blobCompressor = blobCompressor,
|
||||
)
|
||||
val globalCalculator = GlobalBlockConflationCalculator(
|
||||
lastBlockNumber = lastProcessedBlockNumber,
|
||||
syncCalculators = createCalculatorsForBlobsAndConflation(logger, compressedBlobCalculator),
|
||||
deferredTriggerConflationCalculators = listOf(deadlineConflationCalculatorRunnerNew),
|
||||
emptyTracesCounters = TracesCountersV2.EMPTY_TRACES_COUNT,
|
||||
log = logger
|
||||
log = logger,
|
||||
)
|
||||
|
||||
val batchesLimit =
|
||||
@@ -384,7 +384,7 @@ class L1DependentApp(
|
||||
conflationCalculator = globalCalculator,
|
||||
blobCalculator = compressedBlobCalculator,
|
||||
metricsFacade = metricsFacade,
|
||||
batchesLimit = batchesLimit
|
||||
batchesLimit = batchesLimit,
|
||||
)
|
||||
}
|
||||
private val conflationService: ConflationService =
|
||||
@@ -396,7 +396,7 @@ class L1DependentApp(
|
||||
maxInflightRequestsPerClient = configs.stateManager.requestLimitPerEndpoint,
|
||||
requestRetry = configs.stateManager.requestRetryConfig,
|
||||
zkStateManagerVersion = configs.stateManager.version,
|
||||
logger = LogManager.getLogger("clients.StateManagerShomeiClient")
|
||||
logger = LogManager.getLogger("clients.StateManagerShomeiClient"),
|
||||
)
|
||||
|
||||
private val lineaSmartContractClientForDataSubmission: LineaRollupSmartContractClient = run {
|
||||
@@ -411,26 +411,26 @@ class L1DependentApp(
|
||||
gasLimit = configs.l1.gasLimit,
|
||||
maxFeePerGasCap = configs.l1.maxFeePerGasCap,
|
||||
maxPriorityFeePerGasCap = configs.l1.maxPriorityFeePerGasCap,
|
||||
maxFeePerBlobGasCap = configs.l1.maxFeePerBlobGasCap
|
||||
)
|
||||
maxFeePerBlobGasCap = configs.l1.maxFeePerBlobGasCap,
|
||||
),
|
||||
)
|
||||
createLineaRollupContractClient(
|
||||
l1Config = configs.l1,
|
||||
transactionManager = createTransactionManager(
|
||||
vertx,
|
||||
configs.dataSubmissionSigner,
|
||||
l1Web3jClient
|
||||
l1Web3jClient,
|
||||
),
|
||||
contractGasProvider = primaryOrFallbackGasProvider,
|
||||
web3jClient = l1Web3jClient,
|
||||
smartContractErrors = smartContractErrors,
|
||||
useEthEstimateGas = configs.blobSubmission.useEthEstimateGas
|
||||
useEthEstimateGas = configs.blobSubmission.useEthEstimateGas,
|
||||
)
|
||||
}
|
||||
|
||||
private val genesisStateProvider = GenesisStateProvider(
|
||||
configs.l1.genesisStateRootHash,
|
||||
configs.l1.genesisShnarfV6
|
||||
configs.l1.genesisShnarfV6,
|
||||
)
|
||||
|
||||
private val blobCompressionProofCoordinator = run {
|
||||
@@ -440,14 +440,14 @@ class L1DependentApp(
|
||||
category = LineaMetricsCategory.BLOB,
|
||||
name = "proven.highest.block.number",
|
||||
description = "Highest proven blob compression block number",
|
||||
measurementSupplier = highestProvenBlobTracker
|
||||
measurementSupplier = highestProvenBlobTracker,
|
||||
)
|
||||
highestProvenBlobTracker
|
||||
}
|
||||
val blobCompressionProofHandler: (BlobCompressionProofUpdate) -> SafeFuture<*> = SimpleCompositeSafeFutureHandler(
|
||||
listOf(
|
||||
maxProvenBlobCache
|
||||
)
|
||||
maxProvenBlobCache,
|
||||
),
|
||||
)
|
||||
|
||||
val blobCompressionProofCoordinator = BlobCompressionProofCoordinator(
|
||||
@@ -457,33 +457,33 @@ class L1DependentApp(
|
||||
rollingBlobShnarfCalculator = RollingBlobShnarfCalculator(
|
||||
blobShnarfCalculator = GoBackedBlobShnarfCalculator(
|
||||
version = ShnarfCalculatorVersion.V1_2,
|
||||
metricsFacade = metricsFacade
|
||||
metricsFacade = metricsFacade,
|
||||
),
|
||||
blobsRepository = blobsRepository,
|
||||
genesisShnarf = genesisStateProvider.shnarf
|
||||
genesisShnarf = genesisStateProvider.shnarf,
|
||||
),
|
||||
blobZkStateProvider = BlobZkStateProviderImpl(
|
||||
zkStateClient = zkStateClient
|
||||
zkStateClient = zkStateClient,
|
||||
),
|
||||
config = BlobCompressionProofCoordinator.Config(
|
||||
pollingInterval = configs.blobCompression.handlerPollingInterval.toKotlinDuration()
|
||||
pollingInterval = configs.blobCompression.handlerPollingInterval.toKotlinDuration(),
|
||||
),
|
||||
blobCompressionProofHandler = blobCompressionProofHandler,
|
||||
metricsFacade = metricsFacade
|
||||
metricsFacade = metricsFacade,
|
||||
)
|
||||
val highestUnprovenBlobTracker = HighestUnprovenBlobTracker(lastProcessedBlockNumber)
|
||||
metricsFacade.createGauge(
|
||||
category = LineaMetricsCategory.BLOB,
|
||||
name = "unproven.highest.block.number",
|
||||
description = "Block number of highest unproven blob produced",
|
||||
measurementSupplier = highestUnprovenBlobTracker
|
||||
measurementSupplier = highestUnprovenBlobTracker,
|
||||
)
|
||||
|
||||
val compositeSafeFutureHandler = SimpleCompositeSafeFutureHandler(
|
||||
listOf(
|
||||
blobCompressionProofCoordinator::handleBlob,
|
||||
highestUnprovenBlobTracker
|
||||
)
|
||||
highestUnprovenBlobTracker,
|
||||
),
|
||||
)
|
||||
conflationCalculator.onBlobCreation(compositeSafeFutureHandler)
|
||||
blobCompressionProofCoordinator
|
||||
@@ -494,14 +494,14 @@ class L1DependentApp(
|
||||
category = LineaMetricsCategory.BLOB,
|
||||
name = "highest.accepted.block.number",
|
||||
description = "Highest accepted blob end block number",
|
||||
measurementSupplier = it
|
||||
measurementSupplier = it,
|
||||
)
|
||||
}
|
||||
|
||||
private val alreadySubmittedBlobsFilter =
|
||||
L1ShnarfBasedAlreadySubmittedBlobsFilter(
|
||||
lineaRollup = lineaSmartContractClientForDataSubmission,
|
||||
acceptedBlobEndBlockNumberConsumer = { highestAcceptedBlobTracker(it) }
|
||||
acceptedBlobEndBlockNumberConsumer = { highestAcceptedBlobTracker(it) },
|
||||
)
|
||||
|
||||
private val latestBlobSubmittedBlockNumberTracker = LatestBlobSubmittedBlockNumberTracker(0UL)
|
||||
@@ -513,14 +513,14 @@ class L1DependentApp(
|
||||
category = LineaMetricsCategory.BLOB,
|
||||
name = "highest.submitted.on.l1",
|
||||
description = "Highest submitted blob end block number on l1",
|
||||
measurementSupplier = { latestBlobSubmittedBlockNumberTracker.get() }
|
||||
measurementSupplier = { latestBlobSubmittedBlockNumberTracker.get() },
|
||||
)
|
||||
|
||||
val blobSubmissionDelayHistogram = metricsFacade.createHistogram(
|
||||
category = LineaMetricsCategory.BLOB,
|
||||
name = "submission.delay",
|
||||
description = "Delay between blob submission and end block timestamps",
|
||||
baseUnit = "seconds"
|
||||
baseUnit = "seconds",
|
||||
)
|
||||
|
||||
val blobSubmittedEventConsumers: Map<Consumer<BlobSubmittedEvent>, String> = mapOf(
|
||||
@@ -529,7 +529,7 @@ class L1DependentApp(
|
||||
} to "Submitted Blob Tracker Consumer",
|
||||
Consumer<BlobSubmittedEvent> { blobSubmission ->
|
||||
blobSubmissionDelayHistogram.record(blobSubmission.getSubmissionDelay().toDouble())
|
||||
} to "Blob Submission Delay Consumer"
|
||||
} to "Blob Submission Delay Consumer",
|
||||
)
|
||||
|
||||
BlobSubmissionCoordinator.create(
|
||||
@@ -537,7 +537,7 @@ class L1DependentApp(
|
||||
configs.blobSubmission.dbPollingInterval.toKotlinDuration(),
|
||||
configs.blobSubmission.proofSubmissionDelay.toKotlinDuration(),
|
||||
configs.blobSubmission.maxBlobsToSubmitPerTick.toUInt(),
|
||||
configs.blobSubmission.targetBlobsToSendPerTransaction.toUInt()
|
||||
configs.blobSubmission.targetBlobsToSendPerTransaction.toUInt(),
|
||||
),
|
||||
blobsRepository = blobsRepository,
|
||||
aggregationsRepository = aggregationsRepository,
|
||||
@@ -546,7 +546,7 @@ class L1DependentApp(
|
||||
alreadySubmittedBlobsFilter = alreadySubmittedBlobsFilter,
|
||||
blobSubmittedEventDispatcher = EventDispatcher(blobSubmittedEventConsumers),
|
||||
vertx = vertx,
|
||||
clock = Clock.System
|
||||
clock = Clock.System,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -554,14 +554,14 @@ class L1DependentApp(
|
||||
private val proofAggregationCoordinatorService: LongRunningService = run {
|
||||
val maxBlobEndBlockNumberTracker = ConsecutiveProvenBlobsProviderWithLastEndBlockNumberTracker(
|
||||
aggregationsRepository,
|
||||
lastProcessedBlockNumber
|
||||
lastProcessedBlockNumber,
|
||||
)
|
||||
|
||||
metricsFacade.createGauge(
|
||||
category = LineaMetricsCategory.BLOB,
|
||||
name = "proven.highest.consecutive.block.number",
|
||||
description = "Highest consecutive proven blob compression block number",
|
||||
measurementSupplier = maxBlobEndBlockNumberTracker
|
||||
measurementSupplier = maxBlobEndBlockNumberTracker,
|
||||
)
|
||||
|
||||
val highestAggregationTracker = HighestULongTracker(lastProcessedBlockNumber)
|
||||
@@ -569,7 +569,7 @@ class L1DependentApp(
|
||||
category = LineaMetricsCategory.AGGREGATION,
|
||||
name = "proven.highest.block.number",
|
||||
description = "Highest proven aggregation block number",
|
||||
measurementSupplier = highestAggregationTracker
|
||||
measurementSupplier = highestAggregationTracker,
|
||||
)
|
||||
|
||||
ProofAggregationCoordinatorService
|
||||
@@ -581,7 +581,7 @@ class L1DependentApp(
|
||||
aggregationDeadline = configs.proofAggregation.aggregationDeadline.toKotlinDuration(),
|
||||
latestBlockProvider = GethCliqueSafeBlockProvider(
|
||||
l2ExtendedWeb3j.web3jClient,
|
||||
GethCliqueSafeBlockProvider.Config(configs.l2.blocksToFinalization.toLong())
|
||||
GethCliqueSafeBlockProvider.Config(configs.l2.blocksToFinalization.toLong()),
|
||||
),
|
||||
maxProofsPerAggregation = configs.proofAggregation.aggregationProofsLimit.toUInt(),
|
||||
startBlockNumberInclusive = lastConsecutiveAggregatedBlockNumber + 1u,
|
||||
@@ -592,9 +592,9 @@ class L1DependentApp(
|
||||
l2Web3jClient,
|
||||
requestRetryConfig = linea.domain.RetryConfig(
|
||||
backoffDelay = 1.seconds,
|
||||
failuresWarningThreshold = 3u
|
||||
failuresWarningThreshold = 3u,
|
||||
),
|
||||
vertx = vertx
|
||||
vertx = vertx,
|
||||
),
|
||||
l2MessageService = Web3JL2MessageServiceSmartContractClient.create(
|
||||
web3jClient = l2Web3jClient,
|
||||
@@ -605,13 +605,13 @@ class L1DependentApp(
|
||||
feeHistoryRewardPercentile = configs.l2.feeHistoryRewardPercentile,
|
||||
transactionManager = l2TransactionManager,
|
||||
smartContractErrors = smartContractErrors,
|
||||
smartContractDeploymentBlockNumber = configs.l2.messageServiceDeploymentBlockNumber
|
||||
smartContractDeploymentBlockNumber = configs.l2.messageServiceDeploymentBlockNumber,
|
||||
),
|
||||
aggregationDeadlineDelay = configs.conflation.conflationDeadlineLastBlockConfirmationDelay.toKotlinDuration(),
|
||||
targetEndBlockNumbers = configs.proofAggregation.targetEndBlocks,
|
||||
metricsFacade = metricsFacade,
|
||||
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.gasPriceCapMultiplierForFinalization
|
||||
).toULong(),
|
||||
maxFeePerBlobGasCap = configs.l1.maxFeePerBlobGasCap
|
||||
)
|
||||
maxFeePerBlobGasCap = configs.l1.maxFeePerBlobGasCap,
|
||||
),
|
||||
)
|
||||
val lineaSmartContractClientForFinalization: LineaRollupSmartContractClient = createLineaRollupContractClient(
|
||||
l1Config = configs.l1,
|
||||
@@ -645,7 +645,7 @@ class L1DependentApp(
|
||||
contractGasProvider = primaryOrFallbackGasProvider,
|
||||
web3jClient = l1Web3jClient,
|
||||
smartContractErrors = smartContractErrors,
|
||||
useEthEstimateGas = configs.aggregationFinalization.useEthEstimateGas
|
||||
useEthEstimateGas = configs.aggregationFinalization.useEthEstimateGas,
|
||||
)
|
||||
|
||||
val latestFinalizationSubmittedBlockNumberTracker = LatestFinalizationSubmittedBlockNumberTracker(0UL)
|
||||
@@ -653,14 +653,14 @@ class L1DependentApp(
|
||||
category = LineaMetricsCategory.AGGREGATION,
|
||||
name = "highest.submitted.on.l1",
|
||||
description = "Highest submitted finalization end block number on l1",
|
||||
measurementSupplier = { latestFinalizationSubmittedBlockNumberTracker.get() }
|
||||
measurementSupplier = { latestFinalizationSubmittedBlockNumberTracker.get() },
|
||||
)
|
||||
|
||||
val finalizationSubmissionDelayHistogram = metricsFacade.createHistogram(
|
||||
category = LineaMetricsCategory.AGGREGATION,
|
||||
name = "submission.delay",
|
||||
description = "Delay between finalization submission and end block timestamps",
|
||||
baseUnit = "seconds"
|
||||
baseUnit = "seconds",
|
||||
)
|
||||
|
||||
val submittedFinalizationConsumers: Map<Consumer<FinalizationSubmittedEvent>, String> = mapOf(
|
||||
@@ -669,13 +669,13 @@ class L1DependentApp(
|
||||
} to "Finalization Submission Consumer",
|
||||
Consumer<FinalizationSubmittedEvent> { finalizationSubmission ->
|
||||
finalizationSubmissionDelayHistogram.record(finalizationSubmission.getSubmissionDelay().toDouble())
|
||||
} to "Finalization Submission Delay Consumer"
|
||||
} to "Finalization Submission Delay Consumer",
|
||||
)
|
||||
|
||||
AggregationFinalizationCoordinator.create(
|
||||
config = AggregationFinalizationCoordinator.Config(
|
||||
configs.aggregationFinalization.dbPollingInterval.toKotlinDuration(),
|
||||
configs.aggregationFinalization.proofSubmissionDelay.toKotlinDuration()
|
||||
configs.aggregationFinalization.proofSubmissionDelay.toKotlinDuration(),
|
||||
),
|
||||
aggregationsRepository = aggregationsRepository,
|
||||
blobsRepository = blobsRepository,
|
||||
@@ -684,10 +684,10 @@ class L1DependentApp(
|
||||
aggregationSubmitter = AggregationSubmitterImpl(
|
||||
lineaRollup = lineaSmartContractClientForFinalization,
|
||||
gasPriceCapProvider = gasPriceCapProviderForFinalization,
|
||||
aggregationSubmittedEventConsumer = EventDispatcher(submittedFinalizationConsumers)
|
||||
aggregationSubmittedEventConsumer = EventDispatcher(submittedFinalizationConsumers),
|
||||
),
|
||||
vertx = vertx,
|
||||
clock = Clock.System
|
||||
clock = Clock.System,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -702,13 +702,13 @@ class L1DependentApp(
|
||||
rpcClient = httpJsonRpcClientFactory.createWithLoadBalancing(
|
||||
endpoints = tracesCounterV2Config.endpoints.toSet(),
|
||||
maxInflightRequestsPerClient = tracesCounterV2Config.requestLimitPerEndpoint,
|
||||
log = tracesCountersLog
|
||||
log = tracesCountersLog,
|
||||
),
|
||||
config = TracesGeneratorJsonRpcClientV2.Config(
|
||||
expectedTracesApiVersion = expectedTracesApiVersionV2
|
||||
expectedTracesApiVersion = expectedTracesApiVersionV2,
|
||||
),
|
||||
retryConfig = tracesCounterV2Config.requestRetryConfig,
|
||||
log = tracesCountersLog
|
||||
log = tracesCountersLog,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -721,13 +721,13 @@ class L1DependentApp(
|
||||
rpcClient = httpJsonRpcClientFactory.createWithLoadBalancing(
|
||||
endpoints = tracesConflationConfigV2.endpoints.toSet(),
|
||||
maxInflightRequestsPerClient = tracesConflationConfigV2.requestLimitPerEndpoint,
|
||||
log = tracesConflationLog
|
||||
log = tracesConflationLog,
|
||||
),
|
||||
config = TracesGeneratorJsonRpcClientV2.Config(
|
||||
expectedTracesApiVersion = expectedTracesApiVersionV2
|
||||
expectedTracesApiVersion = expectedTracesApiVersionV2,
|
||||
),
|
||||
retryConfig = tracesConflationConfigV2.requestRetryConfig,
|
||||
log = tracesConflationLog
|
||||
log = tracesConflationLog,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -738,7 +738,7 @@ class L1DependentApp(
|
||||
category = LineaMetricsCategory.BATCH,
|
||||
name = "proven.highest.block.number",
|
||||
description = "Highest proven batch execution block number",
|
||||
measurementSupplier = highestProvenBatchTracker
|
||||
measurementSupplier = highestProvenBatchTracker,
|
||||
)
|
||||
highestProvenBatchTracker
|
||||
}
|
||||
@@ -746,12 +746,12 @@ class L1DependentApp(
|
||||
val batchProofHandler = SimpleCompositeSafeFutureHandler(
|
||||
listOf(
|
||||
maxProvenBatchCache,
|
||||
BatchProofHandlerImpl(batchesRepository)::acceptNewBatch
|
||||
)
|
||||
BatchProofHandlerImpl(batchesRepository)::acceptNewBatch,
|
||||
),
|
||||
)
|
||||
val executionProverClient: ExecutionProverClientV2 = proverClientFactory.executionProverClient(
|
||||
tracesVersion = configs.traces.rawExecutionTracesVersion,
|
||||
stateManagerVersion = configs.stateManager.version
|
||||
stateManagerVersion = configs.stateManager.version,
|
||||
)
|
||||
|
||||
val proofGeneratingConflationHandlerImpl = ProofGeneratingConflationHandlerImpl(
|
||||
@@ -762,15 +762,15 @@ class L1DependentApp(
|
||||
web3jClient = l2Web3jClient,
|
||||
requestRetryConfig = linea.domain.RetryConfig(
|
||||
backoffDelay = 1.seconds,
|
||||
failuresWarningThreshold = 3u
|
||||
failuresWarningThreshold = 3u,
|
||||
),
|
||||
vertx = vertx
|
||||
vertx = vertx,
|
||||
),
|
||||
messageServiceAddress = configs.l2.messageServiceAddress
|
||||
messageServiceAddress = configs.l2.messageServiceAddress,
|
||||
),
|
||||
batchProofHandler = batchProofHandler,
|
||||
vertx = vertx,
|
||||
config = ProofGeneratingConflationHandlerImpl.Config(5.seconds)
|
||||
config = ProofGeneratingConflationHandlerImpl.Config(5.seconds),
|
||||
)
|
||||
|
||||
val highestConflationTracker = HighestConflationTracker(lastProcessedBlockNumber)
|
||||
@@ -778,12 +778,12 @@ class L1DependentApp(
|
||||
category = LineaMetricsCategory.CONFLATION,
|
||||
name = "last.block.number",
|
||||
description = "Last conflated block number",
|
||||
measurementSupplier = highestConflationTracker
|
||||
measurementSupplier = highestConflationTracker,
|
||||
)
|
||||
val conflationsCounter = metricsFacade.createCounter(
|
||||
category = LineaMetricsCategory.CONFLATION,
|
||||
name = "counter",
|
||||
description = "Counter of new conflations"
|
||||
description = "Counter of new conflations",
|
||||
)
|
||||
|
||||
SimpleCompositeSafeFutureHandler(
|
||||
@@ -793,8 +793,8 @@ class L1DependentApp(
|
||||
{
|
||||
conflationsCounter.increment()
|
||||
SafeFuture.COMPLETE
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -804,20 +804,20 @@ class L1DependentApp(
|
||||
conflationService = conflationService,
|
||||
tracesCountersClient = tracesCountersClient,
|
||||
vertx = vertx,
|
||||
encoder = BlockRLPEncoder
|
||||
encoder = BlockRLPEncoder,
|
||||
)
|
||||
}
|
||||
|
||||
private val lastProvenBlockNumberProvider = run {
|
||||
val lastProvenConsecutiveBatchBlockNumberProvider = BatchesRepoBasedLastProvenBlockNumberProvider(
|
||||
lastProcessedBlockNumber.toLong(),
|
||||
batchesRepository
|
||||
batchesRepository,
|
||||
)
|
||||
metricsFacade.createGauge(
|
||||
category = LineaMetricsCategory.BATCH,
|
||||
name = "proven.highest.consecutive.block.number",
|
||||
description = "Highest proven consecutive execution batch block number",
|
||||
measurementSupplier = { lastProvenConsecutiveBatchBlockNumberProvider.getLastKnownProvenBlockNumber() }
|
||||
measurementSupplier = { lastProvenConsecutiveBatchBlockNumberProvider.getLastKnownProvenBlockNumber() },
|
||||
)
|
||||
lastProvenConsecutiveBatchBlockNumberProvider
|
||||
}
|
||||
@@ -837,8 +837,8 @@ class L1DependentApp(
|
||||
// We need to add 1 to l2InclusiveBlockNumberToStopAndFlushAggregation because conflation calculator requires
|
||||
// block_number = l2InclusiveBlockNumberToStopAndFlushAggregation + 1 to trigger conflation at
|
||||
// l2InclusiveBlockNumberToStopAndFlushAggregation
|
||||
lastL2BlockNumberToProcessInclusive = configs.l2InclusiveBlockNumberToStopAndFlushAggregation?.let { it + 1uL }
|
||||
)
|
||||
lastL2BlockNumberToProcessInclusive = configs.l2InclusiveBlockNumberToStopAndFlushAggregation?.let { it + 1uL },
|
||||
),
|
||||
)
|
||||
blockCreationMonitor
|
||||
}
|
||||
@@ -847,7 +847,7 @@ class L1DependentApp(
|
||||
val l1BasedLastFinalizedBlockProvider = L1BasedLastFinalizedBlockProvider(
|
||||
vertx,
|
||||
lineaRollupClient,
|
||||
configs.conflation.consistentNumberOfBlocksOnL1ToWait.toUInt()
|
||||
configs.conflation.consistentNumberOfBlocksOnL1ToWait.toUInt(),
|
||||
)
|
||||
return l1BasedLastFinalizedBlockProvider.getLastFinalizedBlock()
|
||||
}
|
||||
@@ -867,12 +867,12 @@ class L1DependentApp(
|
||||
l2HighestBlockTag = configs.messageAnchoring.l2HighestBlockTag,
|
||||
anchoringTickInterval = configs.messageAnchoring.anchoringTickInterval,
|
||||
messageQueueCapacity = configs.messageAnchoring.messageQueueCapacity,
|
||||
maxMessagesToAnchorPerL2Transaction = configs.messageAnchoring.maxMessagesToAnchorPerL2Transaction
|
||||
maxMessagesToAnchorPerL2Transaction = configs.messageAnchoring.maxMessagesToAnchorPerL2Transaction,
|
||||
),
|
||||
l1EthApiClient = createEthApiClient(
|
||||
web3jClient = l1Web3jClient,
|
||||
requestRetryConfig = null,
|
||||
vertx = vertx
|
||||
vertx = vertx,
|
||||
),
|
||||
l2MessageService = Web3JL2MessageServiceSmartContractClient.create(
|
||||
web3jClient = l2Web3jClient,
|
||||
@@ -883,8 +883,8 @@ class L1DependentApp(
|
||||
feeHistoryRewardPercentile = configs.l2.feeHistoryRewardPercentile,
|
||||
transactionManager = l2TransactionManager,
|
||||
smartContractErrors = smartContractErrors,
|
||||
smartContractDeploymentBlockNumber = configs.l2.messageServiceDeploymentBlockNumber
|
||||
)
|
||||
smartContractDeploymentBlockNumber = configs.l2.messageServiceDeploymentBlockNumber,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
DisabledLongRunningService
|
||||
@@ -897,7 +897,7 @@ class L1DependentApp(
|
||||
httpJsonRpcClientFactory = httpJsonRpcClientFactory,
|
||||
l1Web3jClient = l1Web3jClient,
|
||||
l1Web3jService = l1Web3jService,
|
||||
config = configs.l2NetworkGasPricingService
|
||||
config = configs.l2NetworkGasPricingService,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
@@ -916,16 +916,16 @@ class L1DependentApp(
|
||||
val l1FeeHistoryWeb3jBlobExtClient = Web3jBlobExtended(
|
||||
HttpService(
|
||||
configs.l1DynamicGasPriceCapService.feeHistoryFetcher.endpoint?.toString()
|
||||
?: configs.l1.ethFeeHistoryEndpoint.toString()
|
||||
)
|
||||
?: configs.l1.ethFeeHistoryEndpoint.toString(),
|
||||
),
|
||||
)
|
||||
|
||||
val l1FeeHistoryFetcher: GasPriceCapFeeHistoryFetcher = GasPriceCapFeeHistoryFetcherImpl(
|
||||
web3jService = l1FeeHistoryWeb3jBlobExtClient,
|
||||
config = GasPriceCapFeeHistoryFetcherImpl.Config(
|
||||
maxBlockCount = configs.l1DynamicGasPriceCapService.feeHistoryFetcher.maxBlockCount,
|
||||
rewardPercentiles = configs.l1DynamicGasPriceCapService.feeHistoryFetcher.rewardPercentiles
|
||||
)
|
||||
rewardPercentiles = configs.l1DynamicGasPriceCapService.feeHistoryFetcher.rewardPercentiles,
|
||||
),
|
||||
)
|
||||
|
||||
FeeHistoryCachingService(
|
||||
@@ -939,12 +939,12 @@ class L1DependentApp(
|
||||
feeHistoryStoragePeriodInBlocks = feeHistoryStoragePeriodInBlocks,
|
||||
feeHistoryWindowInBlocks = feeHistoryPercentileWindowInBlocks,
|
||||
numOfBlocksBeforeLatest =
|
||||
configs.l1DynamicGasPriceCapService.feeHistoryFetcher.numOfBlocksBeforeLatest
|
||||
configs.l1DynamicGasPriceCapService.feeHistoryFetcher.numOfBlocksBeforeLatest,
|
||||
),
|
||||
vertx = vertx,
|
||||
web3jClient = l1Web3jClient,
|
||||
feeHistoryFetcher = l1FeeHistoryFetcher,
|
||||
feeHistoriesRepository = l1FeeHistoriesRepository
|
||||
feeHistoriesRepository = l1FeeHistoriesRepository,
|
||||
)
|
||||
} else {
|
||||
DisabledLongRunningService
|
||||
@@ -955,7 +955,7 @@ class L1DependentApp(
|
||||
category = LineaMetricsCategory.AGGREGATION,
|
||||
name = "highest.accepted.block.number",
|
||||
description = "Highest finalized accepted end block number",
|
||||
measurementSupplier = it
|
||||
measurementSupplier = it,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -967,11 +967,11 @@ class L1DependentApp(
|
||||
"finalized records cleanup" to RecordsCleanupFinalizationHandler(
|
||||
batchesRepository = batchesRepository,
|
||||
blobsRepository = blobsRepository,
|
||||
aggregationsRepository = aggregationsRepository
|
||||
aggregationsRepository = aggregationsRepository,
|
||||
),
|
||||
"highest_accepted_finalization_on_l1" to FinalizationHandler { update: FinalizationMonitor.FinalizationUpdate ->
|
||||
highestAcceptedFinalizationTracker(update.blockNumber)
|
||||
}
|
||||
},
|
||||
)
|
||||
.forEach { (handlerName, handler) ->
|
||||
l1FinalizationMonitor.addFinalizationHandler(handlerName, handler)
|
||||
@@ -984,7 +984,7 @@ class L1DependentApp(
|
||||
lastConsecutiveAggregatedBlockNumber = lastConsecutiveAggregatedBlockNumber,
|
||||
batchesRepository = batchesRepository,
|
||||
blobsRepository = blobsRepository,
|
||||
aggregationsRepository = aggregationsRepository
|
||||
aggregationsRepository = aggregationsRepository,
|
||||
)
|
||||
.thenCompose { l1FinalizationMonitor.start() }
|
||||
.thenCompose { l1FinalizationHandlerForShomeiRpc.start() }
|
||||
@@ -1016,7 +1016,7 @@ class L1DependentApp(
|
||||
blockCreationMonitor.stop(),
|
||||
deadlineConflationCalculatorRunnerOld.stop(),
|
||||
deadlineConflationCalculatorRunnerNew.stop(),
|
||||
blobCompressionProofCoordinator.stop()
|
||||
blobCompressionProofCoordinator.stop(),
|
||||
)
|
||||
.thenCompose { SafeFuture.fromRunnable { l1Web3jClient.shutdown() } }
|
||||
.thenApply { log.info("L1App Stopped") }
|
||||
@@ -1029,7 +1029,7 @@ class L1DependentApp(
|
||||
lastConsecutiveAggregatedBlockNumber: ULong,
|
||||
batchesRepository: BatchesRepository,
|
||||
blobsRepository: BlobsRepository,
|
||||
aggregationsRepository: AggregationsRepository
|
||||
aggregationsRepository: AggregationsRepository,
|
||||
): SafeFuture<*> {
|
||||
val blockNumberInclusiveToDeleteFrom = lastProcessedBlockNumber + 1u
|
||||
val cleanupBatches = batchesRepository.deleteBatchesAfterBlockNumber(blockNumberInclusiveToDeleteFrom.toLong())
|
||||
@@ -1046,7 +1046,7 @@ class L1DependentApp(
|
||||
*/
|
||||
fun resumeConflationFrom(
|
||||
aggregationsRepository: AggregationsRepository,
|
||||
lastFinalizedBlock: ULong
|
||||
lastFinalizedBlock: ULong,
|
||||
): SafeFuture<ULong> {
|
||||
return aggregationsRepository
|
||||
.findConsecutiveProvenBlobs(lastFinalizedBlock.toLong() + 1)
|
||||
@@ -1061,7 +1061,7 @@ class L1DependentApp(
|
||||
|
||||
fun resumeAggregationFrom(
|
||||
aggregationsRepository: AggregationsRepository,
|
||||
lastFinalizedBlock: ULong
|
||||
lastFinalizedBlock: ULong,
|
||||
): SafeFuture<ULong> {
|
||||
return aggregationsRepository
|
||||
.findHighestConsecutiveEndBlockNumber(lastFinalizedBlock.toLong() + 1)
|
||||
@@ -1075,7 +1075,7 @@ class L1DependentApp(
|
||||
httpJsonRpcClientFactory: VertxHttpJsonRpcClientFactory,
|
||||
lineaRollupClient: LineaRollupSmartContractClientReadOnly,
|
||||
l2Web3jClient: Web3j,
|
||||
vertx: Vertx
|
||||
vertx: Vertx,
|
||||
): LongRunningService {
|
||||
if (type2StateProofProviderConfig == null ||
|
||||
type2StateProofProviderConfig.disabled ||
|
||||
@@ -1091,7 +1091,7 @@ class L1DependentApp(
|
||||
vertx = vertx,
|
||||
rpcClient = httpJsonRpcClientFactory.create(it, log = log),
|
||||
retryConfig = type2StateProofProviderConfig.requestRetryConfig,
|
||||
log = log
|
||||
log = log,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1103,16 +1103,16 @@ class L1DependentApp(
|
||||
config =
|
||||
FinalizationMonitorImpl.Config(
|
||||
pollingInterval = type2StateProofProviderConfig.l1PollingInterval.toKotlinDuration(),
|
||||
l1QueryBlockTag = type2StateProofProviderConfig.l1QueryBlockTag
|
||||
l1QueryBlockTag = type2StateProofProviderConfig.l1QueryBlockTag,
|
||||
),
|
||||
contract = lineaRollupClient,
|
||||
l2Client = l2Web3jClient,
|
||||
vertx = vertx
|
||||
vertx = vertx,
|
||||
)
|
||||
|
||||
l1FinalizationMonitor.addFinalizationHandler("type 2 state proof provider finalization updates", {
|
||||
finalizedBlockNotifier.updateFinalizedBlock(
|
||||
BlockNumberAndHash(it.blockNumber, it.blockHash.toArray())
|
||||
BlockNumberAndHash(it.blockNumber, it.blockHash.toArray()),
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
@@ -28,12 +28,12 @@ class L2NetworkGasPricingService(
|
||||
httpJsonRpcClientFactory: VertxHttpJsonRpcClientFactory,
|
||||
l1Web3jClient: Web3j,
|
||||
l1Web3jService: Web3jBlobExtended,
|
||||
config: Config
|
||||
config: Config,
|
||||
) : LongRunningService {
|
||||
data class LegacyGasPricingCalculatorConfig(
|
||||
val transactionCostCalculatorConfig: TransactionCostCalculator.Config?,
|
||||
val naiveGasPricingCalculatorConfig: GasUsageRatioWeightedAverageFeesCalculator.Config?,
|
||||
val legacyGasPricingCalculatorBounds: BoundableFeeCalculator.Config
|
||||
val legacyGasPricingCalculatorBounds: BoundableFeeCalculator.Config,
|
||||
)
|
||||
|
||||
data class Config(
|
||||
@@ -46,23 +46,23 @@ class L2NetworkGasPricingService(
|
||||
val variableFeesCalculatorConfig: VariableFeesCalculator.Config,
|
||||
val variableFeesCalculatorBounds: BoundableFeeCalculator.Config,
|
||||
val extraDataCalculatorConfig: MinerExtraDataV1CalculatorImpl.Config,
|
||||
val extraDataUpdaterConfig: ExtraDataV1UpdaterImpl.Config
|
||||
val extraDataUpdaterConfig: ExtraDataV1UpdaterImpl.Config,
|
||||
)
|
||||
private val log = LogManager.getLogger(this::class.java)
|
||||
|
||||
private val gasPricingFeesFetcher: FeesFetcher = FeeHistoryFetcherImpl(
|
||||
l1Web3jClient,
|
||||
l1Web3jService,
|
||||
config.feeHistoryFetcherConfig
|
||||
config.feeHistoryFetcherConfig,
|
||||
)
|
||||
|
||||
private val boundedVariableCostCalculator = run {
|
||||
val variableCostCalculator = VariableFeesCalculator(
|
||||
config.variableFeesCalculatorConfig
|
||||
config.variableFeesCalculatorConfig,
|
||||
)
|
||||
BoundableFeeCalculator(
|
||||
config = config.variableFeesCalculatorBounds,
|
||||
feesCalculator = variableCostCalculator
|
||||
feesCalculator = variableCostCalculator,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -71,12 +71,12 @@ class L2NetworkGasPricingService(
|
||||
TransactionCostCalculator(boundedVariableCostCalculator, config.legacy.transactionCostCalculatorConfig)
|
||||
} else {
|
||||
GasUsageRatioWeightedAverageFeesCalculator(
|
||||
config.legacy.naiveGasPricingCalculatorConfig!!
|
||||
config.legacy.naiveGasPricingCalculatorConfig!!,
|
||||
)
|
||||
}
|
||||
BoundableFeeCalculator(
|
||||
config.legacy.legacyGasPricingCalculatorBounds,
|
||||
baseCalculator
|
||||
baseCalculator,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ class L2NetworkGasPricingService(
|
||||
if (config.jsonRpcGasPriceUpdaterConfig != null) {
|
||||
val l2SetGasPriceUpdater: GasPriceUpdater = GasPriceUpdaterImpl(
|
||||
httpJsonRpcClientFactory = httpJsonRpcClientFactory,
|
||||
config = config.jsonRpcGasPriceUpdaterConfig
|
||||
config = config.jsonRpcGasPriceUpdaterConfig,
|
||||
)
|
||||
|
||||
MinMineableFeesPricerService(
|
||||
@@ -92,7 +92,7 @@ class L2NetworkGasPricingService(
|
||||
vertx = vertx,
|
||||
feesFetcher = gasPricingFeesFetcher,
|
||||
feesCalculator = legacyGasPricingCalculator,
|
||||
gasPriceUpdater = l2SetGasPriceUpdater
|
||||
gasPriceUpdater = l2SetGasPriceUpdater,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
@@ -106,12 +106,12 @@ class L2NetworkGasPricingService(
|
||||
minerExtraDataCalculatorImpl = MinerExtraDataV1CalculatorImpl(
|
||||
config = config.extraDataCalculatorConfig,
|
||||
variableFeesCalculator = boundedVariableCostCalculator,
|
||||
legacyFeesCalculator = legacyGasPricingCalculator
|
||||
legacyFeesCalculator = legacyGasPricingCalculator,
|
||||
),
|
||||
extraDataUpdater = ExtraDataV1UpdaterImpl(
|
||||
httpJsonRpcClientFactory = httpJsonRpcClientFactory,
|
||||
config = config.extraDataUpdaterConfig
|
||||
)
|
||||
config = config.extraDataUpdaterConfig,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
@@ -128,7 +128,7 @@ class L2NetworkGasPricingService(
|
||||
override fun stop(): CompletableFuture<Unit> {
|
||||
return SafeFuture.allOf(
|
||||
minMineableFeesPricerService?.stop() ?: SafeFuture.completedFuture(Unit),
|
||||
extraDataPricerService?.stop() ?: SafeFuture.completedFuture(Unit)
|
||||
extraDataPricerService?.stop() ?: SafeFuture.completedFuture(Unit),
|
||||
)
|
||||
.thenApply { }
|
||||
.thenPeek {
|
||||
|
||||
@@ -27,7 +27,7 @@ class L1BasedLastFinalizedBlockProvider(
|
||||
private val lineaRollupSmartContractClient: LineaRollupSmartContractClientReadOnly,
|
||||
private val consistentNumberOfBlocksOnL1: UInt,
|
||||
private val numberOfRetries: UInt = Int.MAX_VALUE.toUInt(),
|
||||
private val pollingInterval: Duration = 2.seconds
|
||||
private val pollingInterval: Duration = 2.seconds,
|
||||
) : LastFinalizedBlockProvider {
|
||||
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",
|
||||
lastObservedBlock.get(),
|
||||
lastPolledBlockNumber,
|
||||
consistentNumberOfBlocksOnL1
|
||||
consistentNumberOfBlocksOnL1,
|
||||
)
|
||||
numberOfObservations.set(1)
|
||||
lastObservedBlock.set(lastPolledBlockNumber)
|
||||
@@ -54,10 +54,10 @@ class L1BasedLastFinalizedBlockProvider(
|
||||
vertx,
|
||||
maxRetries = numberOfRetries.toInt(),
|
||||
backoffDelay = pollingInterval,
|
||||
stopRetriesPredicate = isConsistentEnough
|
||||
stopRetriesPredicate = isConsistentEnough,
|
||||
) {
|
||||
lineaRollupSmartContractClient.finalizedL2BlockNumber(
|
||||
blockParameter = BlockParameter.Tag.LATEST
|
||||
blockParameter = BlockParameter.Tag.LATEST,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,14 +20,14 @@ class BlockParameterDecoder : Decoder<BlockParameter> {
|
||||
BlockParameter.parse(node.value)
|
||||
}.fold(
|
||||
{ it.valid() },
|
||||
{ ConfigFailure.DecodeError(node, type).invalid() }
|
||||
{ ConfigFailure.DecodeError(node, type).invalid() },
|
||||
)
|
||||
|
||||
is LongNode -> runCatching {
|
||||
BlockParameter.fromNumber(node.value)
|
||||
}.fold(
|
||||
{ it.valid() },
|
||||
{ ConfigFailure.DecodeError(node, type).invalid() }
|
||||
{ ConfigFailure.DecodeError(node, type).invalid() },
|
||||
)
|
||||
|
||||
else -> ConfigFailure.DecodeError(node, type).invalid()
|
||||
|
||||
@@ -29,7 +29,7 @@ import kotlin.time.toJavaDuration
|
||||
import kotlin.time.toKotlinDuration
|
||||
|
||||
data class ApiConfig(
|
||||
val observabilityPort: UInt
|
||||
val observabilityPort: UInt,
|
||||
)
|
||||
|
||||
data class ConflationConfig(
|
||||
@@ -42,7 +42,7 @@ data class ConflationConfig(
|
||||
private var _smartContractErrors: SmartContractErrors?,
|
||||
val fetchBlocksLimit: Int,
|
||||
@ConfigAlias("conflation-target-end-block-numbers")
|
||||
private val _conflationTargetEndBlockNumbers: List<Long> = emptyList()
|
||||
private val _conflationTargetEndBlockNumbers: List<Long> = emptyList(),
|
||||
) {
|
||||
|
||||
init {
|
||||
@@ -84,7 +84,7 @@ data class RequestRetryConfigTomlFriendly(
|
||||
override val maxRetries: Int? = null,
|
||||
override val timeout: Duration? = null,
|
||||
override val backoffDelay: Duration = 1.milliseconds.toJavaDuration(),
|
||||
val failuresWarningThreshold: Int = 0
|
||||
val failuresWarningThreshold: Int = 0,
|
||||
) : RetryConfig {
|
||||
init {
|
||||
maxRetries?.also {
|
||||
@@ -105,25 +105,25 @@ data class RequestRetryConfigTomlFriendly(
|
||||
maxRetries = maxRetries?.toUInt(),
|
||||
timeout = timeout?.toKotlinDuration(),
|
||||
backoffDelay = backoffDelay.toKotlinDuration(),
|
||||
failuresWarningThreshold = failuresWarningThreshold.toUInt()
|
||||
failuresWarningThreshold = failuresWarningThreshold.toUInt(),
|
||||
)
|
||||
|
||||
internal val asDomain: linea.domain.RetryConfig = linea.domain.RetryConfig(
|
||||
maxRetries = maxRetries?.toUInt(),
|
||||
timeout = timeout?.toKotlinDuration(),
|
||||
backoffDelay = backoffDelay.toKotlinDuration(),
|
||||
failuresWarningThreshold = failuresWarningThreshold.toUInt()
|
||||
failuresWarningThreshold = failuresWarningThreshold.toUInt(),
|
||||
)
|
||||
|
||||
companion object {
|
||||
fun endlessRetry(
|
||||
backoffDelay: Duration,
|
||||
failuresWarningThreshold: Int
|
||||
failuresWarningThreshold: Int,
|
||||
) = RequestRetryConfigTomlFriendly(
|
||||
maxRetries = null,
|
||||
timeout = null,
|
||||
backoffDelay = backoffDelay,
|
||||
failuresWarningThreshold = failuresWarningThreshold
|
||||
failuresWarningThreshold = failuresWarningThreshold,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -131,7 +131,7 @@ data class RequestRetryConfigTomlFriendly(
|
||||
data class PersistenceRetryConfig(
|
||||
override val maxRetries: Int? = null,
|
||||
override val backoffDelay: Duration = 1.seconds.toJavaDuration(),
|
||||
override val timeout: Duration? = 10.minutes.toJavaDuration()
|
||||
override val timeout: Duration? = 10.minutes.toJavaDuration(),
|
||||
) : RetryConfig
|
||||
|
||||
internal interface RequestRetryConfigurable {
|
||||
@@ -144,7 +144,7 @@ data class BlobCompressionConfig(
|
||||
val blobSizeLimit: Int,
|
||||
@ConfigAlias("batches-limit")
|
||||
private val _batchesLimit: Int? = null,
|
||||
val handlerPollingInterval: Duration
|
||||
val handlerPollingInterval: Duration,
|
||||
) {
|
||||
init {
|
||||
_batchesLimit?.also {
|
||||
@@ -163,7 +163,7 @@ data class AggregationConfig(
|
||||
val deadlineCheckInterval: Duration,
|
||||
val aggregationSizeMultipleOf: Int = 1,
|
||||
@ConfigAlias("target-end-blocks")
|
||||
private val _targetEndBlocks: List<Long> = emptyList()
|
||||
private val _targetEndBlocks: List<Long> = emptyList(),
|
||||
) {
|
||||
val targetEndBlocks: List<ULong> = _targetEndBlocks.map { it.toULong() }
|
||||
|
||||
@@ -177,12 +177,12 @@ data class TracesConfig(
|
||||
val blobCompressorVersion: BlobCompressorVersion,
|
||||
val expectedTracesApiVersionV2: String,
|
||||
val countersV2: FunctionalityEndpoint,
|
||||
val conflationV2: FunctionalityEndpoint
|
||||
val conflationV2: FunctionalityEndpoint,
|
||||
) {
|
||||
data class FunctionalityEndpoint(
|
||||
val endpoints: List<URL>,
|
||||
val requestLimitPerEndpoint: UInt,
|
||||
override val requestRetry: RequestRetryConfigTomlFriendly
|
||||
override val requestRetry: RequestRetryConfigTomlFriendly,
|
||||
) : RequestRetryConfigurable {
|
||||
init {
|
||||
require(requestLimitPerEndpoint > 0u) { "requestLimitPerEndpoint must be greater than 0" }
|
||||
@@ -194,7 +194,7 @@ data class StateManagerClientConfig(
|
||||
val version: String,
|
||||
val endpoints: List<URL>,
|
||||
val requestLimitPerEndpoint: UInt,
|
||||
override val requestRetry: RequestRetryConfigTomlFriendly
|
||||
override val requestRetry: RequestRetryConfigTomlFriendly,
|
||||
) : RequestRetryConfigurable {
|
||||
init {
|
||||
require(requestLimitPerEndpoint > 0u) { "requestLimitPerEndpoint must be greater than 0" }
|
||||
@@ -210,7 +210,7 @@ data class BlobSubmissionConfig(
|
||||
val maxBlobsToSubmitPerTick: Int = maxBlobsToReturn,
|
||||
val targetBlobsToSendPerTransaction: Int = 9,
|
||||
val useEthEstimateGas: Boolean = false,
|
||||
override var disabled: Boolean = false
|
||||
override var disabled: Boolean = false,
|
||||
) : FeatureToggleable {
|
||||
init {
|
||||
require(maxBlobsToReturn > 0) { "maxBlobsToReturn must be greater than 0" }
|
||||
@@ -226,7 +226,7 @@ data class AggregationFinalizationConfig(
|
||||
val maxAggregationsToFinalizePerTick: Int,
|
||||
val proofSubmissionDelay: Duration,
|
||||
val useEthEstimateGas: Boolean = false,
|
||||
override var disabled: Boolean = false
|
||||
override var disabled: Boolean = false,
|
||||
) : FeatureToggleable {
|
||||
init {
|
||||
require(maxAggregationsToFinalizePerTick > 0) {
|
||||
@@ -243,7 +243,7 @@ data class DatabaseConfig(
|
||||
val schema: String,
|
||||
val readPoolSize: Int,
|
||||
val readPipeliningLimit: Int,
|
||||
val transactionalPoolSize: Int
|
||||
val transactionalPoolSize: Int,
|
||||
)
|
||||
|
||||
data class L1Config(
|
||||
@@ -268,7 +268,7 @@ data class L1Config(
|
||||
val blockTime: Duration = Duration.parse("PT12S"),
|
||||
@ConfigAlias("eth-fee-history-endpoint") private val _ethFeeHistoryEndpoint: URL?,
|
||||
@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
|
||||
get() = _ethFeeHistoryEndpoint ?: rpcEndpoint
|
||||
@@ -303,7 +303,7 @@ data class L2Config(
|
||||
val lastHashSearchWindow: UInt,
|
||||
val anchoringReceiptPollingInterval: Duration,
|
||||
val maxReceiptRetries: UInt,
|
||||
val newBlockPollingInterval: Duration
|
||||
val newBlockPollingInterval: Duration,
|
||||
) {
|
||||
init {
|
||||
messageServiceAddress.assertIsValidAddress("messageServiceAddress")
|
||||
@@ -313,11 +313,11 @@ data class L2Config(
|
||||
data class SignerConfig(
|
||||
val type: Type,
|
||||
val web3signer: Web3SignerConfig?,
|
||||
val web3j: Web3jConfig?
|
||||
val web3j: Web3jConfig?,
|
||||
) {
|
||||
enum class Type {
|
||||
Web3j,
|
||||
Web3Signer
|
||||
Web3Signer,
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -334,14 +334,14 @@ data class SignerConfig(
|
||||
}
|
||||
|
||||
data class Web3jConfig(
|
||||
val privateKey: Masked
|
||||
val privateKey: Masked,
|
||||
)
|
||||
|
||||
data class Web3SignerConfig(
|
||||
val endpoint: String,
|
||||
val maxPoolSize: UInt,
|
||||
val keepAlive: Boolean,
|
||||
val publicKey: String
|
||||
val publicKey: String,
|
||||
)
|
||||
|
||||
interface FeatureToggleable {
|
||||
@@ -354,7 +354,7 @@ data class L1DynamicGasPriceCapServiceConfig(
|
||||
val gasPriceCapCalculation: GasPriceCapCalculation,
|
||||
val feeHistoryFetcher: FeeHistoryFetcher,
|
||||
val feeHistoryStorage: FeeHistoryStorage,
|
||||
override var disabled: Boolean = false
|
||||
override var disabled: Boolean = false,
|
||||
) : FeatureToggleable {
|
||||
data class GasPriceCapCalculation(
|
||||
val adjustmentConstant: UInt,
|
||||
@@ -366,7 +366,7 @@ data class L1DynamicGasPriceCapServiceConfig(
|
||||
val gasPriceCapsCheckCoefficient: Double,
|
||||
val historicBaseFeePerBlobGasLowerBound: ULong,
|
||||
val historicAvgRewardConstant: ULong?,
|
||||
val timeOfDayMultipliers: TimeOfDayMultipliers?
|
||||
val timeOfDayMultipliers: TimeOfDayMultipliers?,
|
||||
) {
|
||||
init {
|
||||
timeOfDayMultipliers?.also {
|
||||
@@ -385,7 +385,7 @@ data class L1DynamicGasPriceCapServiceConfig(
|
||||
require(timeOfDayMultiplier.value > 0.0) {
|
||||
throw IllegalStateException(
|
||||
"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(
|
||||
val storagePeriod: Duration
|
||||
val storagePeriod: Duration,
|
||||
) {
|
||||
init {
|
||||
require(storagePeriod <= MAX_FEE_HISTORIES_STORAGE_PERIOD.toJavaDuration()) {
|
||||
@@ -418,12 +418,12 @@ data class L1DynamicGasPriceCapServiceConfig(
|
||||
val maxBlockCount: UInt,
|
||||
val rewardPercentiles: List<Double>,
|
||||
val numOfBlocksBeforeLatest: UInt = 4U,
|
||||
val endpoint: URL?
|
||||
val endpoint: URL?,
|
||||
) {
|
||||
init {
|
||||
require(
|
||||
maxBlockCount > 0U &&
|
||||
maxBlockCount <= MAX_FEE_HISTORY_BLOCK_COUNT
|
||||
maxBlockCount <= MAX_FEE_HISTORY_BLOCK_COUNT,
|
||||
) {
|
||||
"maxBlockCount must be greater than 0 and " +
|
||||
"less than or equal to $MAX_FEE_HISTORY_BLOCK_COUNT"
|
||||
@@ -431,7 +431,7 @@ data class L1DynamicGasPriceCapServiceConfig(
|
||||
|
||||
require(
|
||||
rewardPercentiles.isNotEmpty() &&
|
||||
rewardPercentiles.size <= MAX_REWARD_PERCENTILES_SIZE
|
||||
rewardPercentiles.size <= MAX_REWARD_PERCENTILES_SIZE,
|
||||
) {
|
||||
"rewardPercentiles must be a non-empty list with " +
|
||||
"maximum length as $MAX_REWARD_PERCENTILES_SIZE."
|
||||
@@ -459,7 +459,7 @@ data class L1DynamicGasPriceCapServiceConfig(
|
||||
|
||||
require(
|
||||
gasPriceCapCalculation.gasFeePercentileWindow
|
||||
>= gasPriceCapCalculation.gasFeePercentileWindowLeeway
|
||||
>= gasPriceCapCalculation.gasFeePercentileWindowLeeway,
|
||||
) {
|
||||
"gasFeePercentileWindow must be at least same length as" +
|
||||
" gasFeePercentileWindowLeeway=${gasPriceCapCalculation.gasFeePercentileWindowLeeway}." +
|
||||
@@ -483,7 +483,7 @@ data class Type2StateProofProviderConfig(
|
||||
val endpoints: List<URL>,
|
||||
val l1QueryBlockTag: BlockParameter.Tag = BlockParameter.Tag.LATEST,
|
||||
val l1PollingInterval: Duration = Duration.ofSeconds(12),
|
||||
override val requestRetry: RequestRetryConfigTomlFriendly
|
||||
override val requestRetry: RequestRetryConfigTomlFriendly,
|
||||
) : FeatureToggleable, RequestRetryConfigurable
|
||||
|
||||
data class TracesLimitsV2ConfigFile(val tracesLimits: Map<TracingModuleV2, UInt>)
|
||||
@@ -515,7 +515,7 @@ data class CoordinatorConfigTomlDto(
|
||||
val l2NetworkGasPricing: L2NetworkGasPricingTomlDto,
|
||||
val l1DynamicGasPriceCapService: L1DynamicGasPriceCapServiceConfig,
|
||||
val testL1Disabled: Boolean = false,
|
||||
val prover: ProverConfigTomlDto
|
||||
val prover: ProverConfigTomlDto,
|
||||
) {
|
||||
fun reified(): CoordinatorConfig = CoordinatorConfig(
|
||||
l2InclusiveBlockNumberToStopAndFlushAggregation = l2InclusiveBlockNumberToStopAndFlushAggregation,
|
||||
@@ -537,13 +537,13 @@ data class CoordinatorConfigTomlDto(
|
||||
l2Signer = l2Signer,
|
||||
messageAnchoring = messageAnchoring.reified(
|
||||
l1DefaultEndpoint = l1.rpcEndpoint,
|
||||
l2DefaultEndpoint = l2.rpcEndpoint
|
||||
l2DefaultEndpoint = l2.rpcEndpoint,
|
||||
),
|
||||
l2NetworkGasPricingService =
|
||||
if (testL1Disabled || l2NetworkGasPricing.disabled) null else l2NetworkGasPricing.reified(),
|
||||
l1DynamicGasPriceCapService = l1DynamicGasPriceCapService,
|
||||
testL1Disabled = testL1Disabled,
|
||||
proversConfig = prover.reified()
|
||||
proversConfig = prover.reified(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -569,7 +569,7 @@ data class CoordinatorConfig(
|
||||
val l2NetworkGasPricingService: L2NetworkGasPricingService.Config?,
|
||||
val l1DynamicGasPriceCapService: L1DynamicGasPriceCapServiceConfig,
|
||||
val testL1Disabled: Boolean = false,
|
||||
val proversConfig: ProversConfig
|
||||
val proversConfig: ProversConfig,
|
||||
) {
|
||||
init {
|
||||
if (l2InclusiveBlockNumberToStopAndFlushAggregation != null) {
|
||||
@@ -583,7 +583,7 @@ data class CoordinatorConfig(
|
||||
|
||||
require(
|
||||
blobCompression.batchesLimit == null ||
|
||||
blobCompression.batchesLimit!! < proofAggregation.aggregationProofsLimit.toUInt()
|
||||
blobCompression.batchesLimit!! < proofAggregation.aggregationProofsLimit.toUInt(),
|
||||
) {
|
||||
"[blob-compression].batchesLimit=${blobCompression.batchesLimit} must be less than " +
|
||||
"[proof-aggregation].aggregationProofsLimit=${proofAggregation.aggregationProofsLimit}"
|
||||
|
||||
@@ -19,7 +19,7 @@ import kotlin.time.toKotlinDuration
|
||||
data class SampleTransactionGasPricingTomlDto(
|
||||
val plainTransferCostMultiplier: Double = 1.0,
|
||||
val compressedTxSize: Int = 125,
|
||||
val expectedGas: Int = 21000
|
||||
val expectedGas: Int = 21000,
|
||||
)
|
||||
|
||||
data class LegacyGasPricingTomlDto(
|
||||
@@ -28,11 +28,11 @@ data class LegacyGasPricingTomlDto(
|
||||
val naiveGasPricing: NaiveGasPricingTomlDto?,
|
||||
val sampleTransactionGasPricing: SampleTransactionGasPricingTomlDto = SampleTransactionGasPricingTomlDto(),
|
||||
val gasPriceUpperBound: ULong,
|
||||
val gasPriceLowerBound: ULong
|
||||
val gasPriceLowerBound: ULong,
|
||||
) {
|
||||
enum class Type {
|
||||
Naive,
|
||||
SampleTransaction
|
||||
SampleTransaction,
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -49,7 +49,7 @@ data class LegacyGasPricingTomlDto(
|
||||
data class NaiveGasPricingTomlDto(
|
||||
val baseFeeCoefficient: Double,
|
||||
val priorityFeeCoefficient: Double,
|
||||
val baseFeeBlobCoefficient: Double
|
||||
val baseFeeBlobCoefficient: Double,
|
||||
)
|
||||
|
||||
data class VariableCostPricingTomlDto(
|
||||
@@ -57,7 +57,7 @@ data class VariableCostPricingTomlDto(
|
||||
val legacyFeesMultiplier: Double,
|
||||
val margin: Double,
|
||||
val variableCostUpperBound: ULong,
|
||||
val variableCostLowerBound: ULong
|
||||
val variableCostLowerBound: ULong,
|
||||
) {
|
||||
init {
|
||||
require(variableCostUpperBound >= variableCostLowerBound) {
|
||||
@@ -69,7 +69,7 @@ data class VariableCostPricingTomlDto(
|
||||
data class JsonRpcPricingPropagationTomlDto(
|
||||
override var disabled: Boolean = false,
|
||||
val gethGasPriceUpdateRecipients: List<URL>,
|
||||
val besuGasPriceUpdateRecipients: List<URL>
|
||||
val besuGasPriceUpdateRecipients: List<URL>,
|
||||
) : FeatureToggleable {
|
||||
init {
|
||||
require(disabled || (gethGasPriceUpdateRecipients.isNotEmpty() || besuGasPriceUpdateRecipients.isNotEmpty())) {
|
||||
@@ -81,7 +81,7 @@ data class JsonRpcPricingPropagationTomlDto(
|
||||
|
||||
data class ExtraDataPricingPropagationTomlDto(
|
||||
override var disabled: Boolean = false,
|
||||
val extraDataUpdateRecipient: URL
|
||||
val extraDataUpdateRecipient: URL,
|
||||
) : FeatureToggleable
|
||||
|
||||
data class L2NetworkGasPricingTomlDto(
|
||||
@@ -99,7 +99,7 @@ data class L2NetworkGasPricingTomlDto(
|
||||
val legacy: LegacyGasPricingTomlDto,
|
||||
val variableCostPricing: VariableCostPricingTomlDto,
|
||||
val jsonRpcPricingPropagation: JsonRpcPricingPropagationTomlDto?,
|
||||
val extraDataPricingPropagation: ExtraDataPricingPropagationTomlDto
|
||||
val extraDataPricingPropagation: ExtraDataPricingPropagationTomlDto,
|
||||
) : FeatureToggleable, RequestRetryConfigurable {
|
||||
init {
|
||||
require(feeHistoryBlockCount > 0) { "feeHistoryBlockCount must be greater than 0" }
|
||||
@@ -124,13 +124,13 @@ data class L2NetworkGasPricingTomlDto(
|
||||
priorityFeeCoefficient = legacy.naiveGasPricing.priorityFeeCoefficient,
|
||||
baseFeeBlobCoefficient = legacy.naiveGasPricing.baseFeeBlobCoefficient,
|
||||
blobSubmissionExpectedExecutionGas = blobSubmissionExpectedExecutionGas,
|
||||
expectedBlobGas = l1BlobGas
|
||||
expectedBlobGas = l1BlobGas,
|
||||
),
|
||||
legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config(
|
||||
legacy.gasPriceUpperBound.toDouble(),
|
||||
legacy.gasPriceLowerBound.toDouble(),
|
||||
0.0
|
||||
)
|
||||
0.0,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -140,14 +140,14 @@ data class L2NetworkGasPricingTomlDto(
|
||||
sampleTransactionCostMultiplier = legacy.sampleTransactionGasPricing.plainTransferCostMultiplier,
|
||||
fixedCostWei = variableCostPricing.gasPriceFixedCost,
|
||||
compressedTxSize = legacy.sampleTransactionGasPricing.compressedTxSize,
|
||||
expectedGas = legacy.sampleTransactionGasPricing.expectedGas
|
||||
expectedGas = legacy.sampleTransactionGasPricing.expectedGas,
|
||||
),
|
||||
naiveGasPricingCalculatorConfig = null,
|
||||
legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config(
|
||||
legacy.gasPriceUpperBound.toDouble(),
|
||||
legacy.gasPriceLowerBound.toDouble(),
|
||||
0.0
|
||||
)
|
||||
0.0,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -155,7 +155,7 @@ data class L2NetworkGasPricingTomlDto(
|
||||
GasPriceUpdaterImpl.Config(
|
||||
gethEndpoints = jsonRpcPricingPropagation.gethGasPriceUpdateRecipients,
|
||||
besuEndPoints = jsonRpcPricingPropagation.besuGasPriceUpdateRecipients,
|
||||
retryConfig = requestRetryConfig
|
||||
retryConfig = requestRetryConfig,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
@@ -163,7 +163,7 @@ data class L2NetworkGasPricingTomlDto(
|
||||
return L2NetworkGasPricingService.Config(
|
||||
feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config(
|
||||
feeHistoryBlockCount = feeHistoryBlockCount.toUInt(),
|
||||
feeHistoryRewardPercentile = feeHistoryRewardPercentile
|
||||
feeHistoryRewardPercentile = feeHistoryRewardPercentile,
|
||||
),
|
||||
legacy = legacyGasPricingConfig,
|
||||
jsonRpcGasPriceUpdaterConfig = gasPriceUpdaterConfig,
|
||||
@@ -174,21 +174,21 @@ data class L2NetworkGasPricingTomlDto(
|
||||
blobSubmissionExpectedExecutionGas = blobSubmissionExpectedExecutionGas.toUInt(),
|
||||
bytesPerDataSubmission = l1BlobGas.toUInt(),
|
||||
expectedBlobGas = bytesPerDataSubmission.toUInt(),
|
||||
margin = variableCostPricing.margin
|
||||
margin = variableCostPricing.margin,
|
||||
),
|
||||
variableFeesCalculatorBounds = BoundableFeeCalculator.Config(
|
||||
feeUpperBound = variableCostPricing.variableCostUpperBound.toDouble(),
|
||||
feeLowerBound = variableCostPricing.variableCostLowerBound.toDouble(),
|
||||
feeMargin = 0.0
|
||||
feeMargin = 0.0,
|
||||
),
|
||||
extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config(
|
||||
fixedCostInKWei = variableCostPricing.gasPriceFixedCost.toKWeiUInt(),
|
||||
ethGasPriceMultiplier = variableCostPricing.legacyFeesMultiplier
|
||||
ethGasPriceMultiplier = variableCostPricing.legacyFeesMultiplier,
|
||||
),
|
||||
extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config(
|
||||
extraDataPricingPropagation.extraDataUpdateRecipient,
|
||||
requestRetryConfig
|
||||
)
|
||||
requestRetryConfig,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ data class MessageAnchoringConfigTomlDto(
|
||||
val l1HighestBlockTag: BlockParameter = BlockParameter.Tag.FINALIZED,
|
||||
val l1RequestRetries: RequestRetryConfigTomlFriendly = RequestRetryConfigTomlFriendly.endlessRetry(
|
||||
backoffDelay = 1.seconds.toJavaDuration(),
|
||||
failuresWarningThreshold = 3
|
||||
failuresWarningThreshold = 3,
|
||||
),
|
||||
val l1EventPollingInterval: Duration = 12.seconds.toJavaDuration(),
|
||||
val l1EventPollingTimeout: Duration = 6.seconds.toJavaDuration(),
|
||||
@@ -24,11 +24,11 @@ data class MessageAnchoringConfigTomlDto(
|
||||
val l2HighestBlockTag: BlockParameter = BlockParameter.Tag.LATEST,
|
||||
val l2RequestRetries: RequestRetryConfigTomlFriendly = RequestRetryConfigTomlFriendly.endlessRetry(
|
||||
backoffDelay = 1.seconds.toJavaDuration(),
|
||||
failuresWarningThreshold = 3
|
||||
failuresWarningThreshold = 3,
|
||||
),
|
||||
val anchoringTickInterval: Duration = 2.seconds.toJavaDuration(),
|
||||
val messageQueueCapacity: Int = 10_000,
|
||||
val maxMessagesToAnchorPerL2Transaction: Int = 100
|
||||
val maxMessagesToAnchorPerL2Transaction: Int = 100,
|
||||
) {
|
||||
init {
|
||||
require(messageQueueCapacity > 0) {
|
||||
@@ -56,7 +56,7 @@ data class MessageAnchoringConfigTomlDto(
|
||||
|
||||
fun reified(
|
||||
l1DefaultEndpoint: URL,
|
||||
l2DefaultEndpoint: URL
|
||||
l2DefaultEndpoint: URL,
|
||||
): MessageAnchoringConfig {
|
||||
return MessageAnchoringConfig(
|
||||
disabled = disabled,
|
||||
@@ -72,7 +72,7 @@ data class MessageAnchoringConfigTomlDto(
|
||||
l1EventSearchBlockChunk = l1EventSearchBlockChunk.toUInt(),
|
||||
anchoringTickInterval = anchoringTickInterval.toKotlinDuration(),
|
||||
messageQueueCapacity = messageQueueCapacity.toUInt(),
|
||||
maxMessagesToAnchorPerL2Transaction = maxMessagesToAnchorPerL2Transaction.toUInt()
|
||||
maxMessagesToAnchorPerL2Transaction = maxMessagesToAnchorPerL2Transaction.toUInt(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -91,5 +91,5 @@ data class MessageAnchoringConfig(
|
||||
val l1EventSearchBlockChunk: UInt,
|
||||
val anchoringTickInterval: kotlin.time.Duration,
|
||||
val messageQueueCapacity: UInt,
|
||||
val maxMessagesToAnchorPerL2Transaction: UInt
|
||||
val maxMessagesToAnchorPerL2Transaction: UInt,
|
||||
) : FeatureToggleable
|
||||
|
||||
@@ -19,13 +19,13 @@ data class ProverConfigTomlDto(
|
||||
val execution: FileSystemTomlDto,
|
||||
val blobCompression: FileSystemTomlDto,
|
||||
val proofAggregation: FileSystemTomlDto,
|
||||
val new: ProverConfigTomlDto? = null
|
||||
val new: ProverConfigTomlDto? = null,
|
||||
) {
|
||||
private fun asProverConfig(): ProverConfig {
|
||||
return ProverConfig(
|
||||
execution = execution.toDomain(),
|
||||
blobCompression = blobCompression.toDomain(),
|
||||
proofAggregation = proofAggregation.toDomain()
|
||||
proofAggregation = proofAggregation.toDomain(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ data class ProverConfigTomlDto(
|
||||
return ProversConfig(
|
||||
proverA = this.asProverConfig(),
|
||||
switchBlockNumberInclusive = new?.switchBlockNumberInclusive?.toULong(),
|
||||
proverB = new?.asProverConfig()
|
||||
proverB = new?.asProverConfig(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ data class FileSystemTomlDto(
|
||||
internal var fsInprogressRequestWritingSuffix: String?,
|
||||
internal var fsInprogressProvingSuffixPattern: String?,
|
||||
internal var fsPollingInterval: Duration?,
|
||||
internal var fsPollingTimeout: Duration?
|
||||
internal var fsPollingTimeout: Duration?,
|
||||
) {
|
||||
internal fun reifyWithRootDefaults(rootConfig: ProverConfigTomlDto) {
|
||||
fsInprogressRequestWritingSuffix = fsInprogressRequestWritingSuffix
|
||||
@@ -85,7 +85,7 @@ data class FileSystemTomlDto(
|
||||
inprogressRequestWritingSuffix = fsInprogressRequestWritingSuffix!!,
|
||||
inprogressProvingSuffixPattern = fsInprogressProvingSuffixPattern!!,
|
||||
pollingInterval = fsPollingInterval!!.toKotlinDuration(),
|
||||
pollingTimeout = fsPollingTimeout!!.toKotlinDuration()
|
||||
pollingTimeout = fsPollingTimeout!!.toKotlinDuration(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,18 +25,18 @@ class BlockCreationMonitor(
|
||||
private val blockCreationListener: BlockCreationListener,
|
||||
private val lastProvenBlockNumberProviderAsync: LastProvenBlockNumberProviderAsync,
|
||||
private val config: Config,
|
||||
private val log: Logger = LogManager.getLogger(BlockCreationMonitor::class.java)
|
||||
private val log: Logger = LogManager.getLogger(BlockCreationMonitor::class.java),
|
||||
) : PeriodicPollingService(
|
||||
vertx = vertx,
|
||||
pollingIntervalMs = config.pollingInterval.inWholeMilliseconds,
|
||||
log = log
|
||||
log = log,
|
||||
) {
|
||||
data class Config(
|
||||
val pollingInterval: Duration,
|
||||
val blocksToFinalization: Long,
|
||||
val blocksFetchLimit: Long,
|
||||
val startingBlockWaitTimeout: Duration = 14.days,
|
||||
val lastL2BlockNumberToProcessInclusive: ULong? = null
|
||||
val lastL2BlockNumberToProcessInclusive: ULong? = null,
|
||||
)
|
||||
|
||||
private val _nexBlockNumberToFetch: AtomicLong = AtomicLong(startingBlockNumberExclusive + 1)
|
||||
@@ -76,7 +76,7 @@ class BlockCreationMonitor(
|
||||
log.warn(
|
||||
"Block {} not found yet. Retrying in {}",
|
||||
startingBlockNumberExclusive,
|
||||
config.pollingInterval
|
||||
config.pollingInterval,
|
||||
)
|
||||
false
|
||||
} else {
|
||||
@@ -84,7 +84,7 @@ class BlockCreationMonitor(
|
||||
expectedParentBlockHash.set(block.hash)
|
||||
true
|
||||
}
|
||||
}
|
||||
},
|
||||
) {
|
||||
web3j.ethGetBlock(startingBlockNumberExclusive.toBlockParameter())
|
||||
}
|
||||
@@ -104,7 +104,7 @@ class BlockCreationMonitor(
|
||||
lastProvenBlockNumber,
|
||||
_nexBlockNumberToFetch.get(),
|
||||
_nexBlockNumberToFetch.get() - lastProvenBlockNumber,
|
||||
config.blocksFetchLimit
|
||||
config.blocksFetchLimit,
|
||||
)
|
||||
SafeFuture.COMPLETE
|
||||
} else if (config.lastL2BlockNumberToProcessInclusive != null &&
|
||||
@@ -115,7 +115,7 @@ class BlockCreationMonitor(
|
||||
"All blocks upto and including lastL2BlockNumberInclusiveToProcess={} have been processed. " +
|
||||
"nextBlockNumberToFetch={}",
|
||||
config.lastL2BlockNumberToProcessInclusive,
|
||||
nexBlockNumberToFetch
|
||||
nexBlockNumberToFetch,
|
||||
)
|
||||
SafeFuture.COMPLETE
|
||||
} else {
|
||||
@@ -128,7 +128,7 @@ class BlockCreationMonitor(
|
||||
log.debug(
|
||||
"updating nexBlockNumberToFetch from {} --> {}",
|
||||
_nexBlockNumberToFetch.get(),
|
||||
_nexBlockNumberToFetch.incrementAndGet()
|
||||
_nexBlockNumberToFetch.incrementAndGet(),
|
||||
)
|
||||
expectedParentBlockHash.set(block.hash)
|
||||
}
|
||||
@@ -140,7 +140,7 @@ class BlockCreationMonitor(
|
||||
block.number,
|
||||
block.hash.encodeHex(),
|
||||
block.parentHash.encodeHex(),
|
||||
expectedParentBlockHash.get().encodeHex()
|
||||
expectedParentBlockHash.get().encodeHex(),
|
||||
)
|
||||
SafeFuture.failedFuture(IllegalStateException("Reorg detected on block ${block.number}"))
|
||||
}
|
||||
@@ -164,7 +164,7 @@ class BlockCreationMonitor(
|
||||
.thenApply {
|
||||
log.debug(
|
||||
"blockCreationListener blockNumber={} resolved with success",
|
||||
payload.number
|
||||
payload.number,
|
||||
)
|
||||
}
|
||||
.whenException { throwable ->
|
||||
@@ -172,7 +172,7 @@ class BlockCreationMonitor(
|
||||
"Failed to notify blockCreationListener: blockNumber={} errorMessage={}",
|
||||
payload.number,
|
||||
throwable.message,
|
||||
throwable
|
||||
throwable,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ class BlockCreationMonitor(
|
||||
"eth_getBlockByNumber({}) failed: errorMessage={}",
|
||||
blockNumber,
|
||||
it.message,
|
||||
it
|
||||
it,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -12,10 +12,10 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture
|
||||
|
||||
class GethCliqueSafeBlockProvider(
|
||||
private val web3j: Web3j,
|
||||
private val config: Config
|
||||
private val config: Config,
|
||||
) : SafeBlockProvider {
|
||||
data class Config(
|
||||
val blocksToFinalization: Long
|
||||
val blocksToFinalization: Long,
|
||||
)
|
||||
|
||||
override fun getLatestSafeBlock(): SafeFuture<Block> {
|
||||
|
||||
@@ -15,7 +15,7 @@ interface LastProvenBlockNumberProviderSync {
|
||||
|
||||
class BatchesRepoBasedLastProvenBlockNumberProvider(
|
||||
startingBlockNumberExclusive: Long,
|
||||
private val batchesRepository: BatchesRepository
|
||||
private val batchesRepository: BatchesRepository,
|
||||
) : LastProvenBlockNumberProviderAsync, LastProvenBlockNumberProviderSync {
|
||||
private var latestL1FinalizedBlock: AtomicLong = AtomicLong(startingBlockNumberExclusive)
|
||||
private var lastProvenBlock: AtomicLong = AtomicLong(startingBlockNumberExclusive)
|
||||
@@ -35,7 +35,7 @@ class BatchesRepoBasedLastProvenBlockNumberProvider(
|
||||
|
||||
private fun findAndCacheLastProvenBlockNumberFromDb(): SafeFuture<Long> {
|
||||
return batchesRepository.findHighestConsecutiveEndBlockNumberFromBlockNumber(
|
||||
latestL1FinalizedBlock.get() + 1
|
||||
latestL1FinalizedBlock.get() + 1,
|
||||
).thenApply {
|
||||
newValue ->
|
||||
if (newValue != null) {
|
||||
|
||||
@@ -3,7 +3,7 @@ package net.consensys.zkevm.ethereum.coordination
|
||||
import tech.pegasys.teku.infrastructure.async.SafeFuture
|
||||
|
||||
class SimpleCompositeSafeFutureHandler<T>(
|
||||
private val handlers: List<(T) -> SafeFuture<*>>
|
||||
private val handlers: List<(T) -> SafeFuture<*>>,
|
||||
) : (T) -> SafeFuture<*> {
|
||||
override fun invoke(arg: T): SafeFuture<Unit> {
|
||||
val handlingFutures =
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.util.function.Supplier
|
||||
|
||||
class ConsecutiveProvenBlobsProviderWithLastEndBlockNumberTracker(
|
||||
private val repository: AggregationsRepository,
|
||||
initialBlockNumber: ULong
|
||||
initialBlockNumber: ULong,
|
||||
) : ConsecutiveProvenBlobsProvider, Supplier<Number> {
|
||||
private val cache = AtomicReference(initialBlockNumber)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import linea.domain.BlockInterval
|
||||
import tech.pegasys.teku.infrastructure.async.SafeFuture
|
||||
|
||||
class BlobZkStateProviderImpl(
|
||||
private val zkStateClient: StateManagerClientV1
|
||||
private val zkStateClient: StateManagerClientV1,
|
||||
) : BlobZkStateProvider {
|
||||
override fun getBlobZKState(blockRange: ULongRange): SafeFuture<BlobZkState> {
|
||||
return zkStateClient
|
||||
@@ -14,7 +14,7 @@ class BlobZkStateProviderImpl(
|
||||
.thenApply {
|
||||
BlobZkState(
|
||||
parentStateRootHash = it.zkParentStateRootHash,
|
||||
finalStateRootHash = it.zkEndStateRootHash
|
||||
finalStateRootHash = it.zkEndStateRootHash,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ class ForkChoiceUpdaterImpl(private val rollupForkChoiceUpdatedClients: List<Rol
|
||||
log.debug(
|
||||
"Updating finalized block: {}, to {} clients",
|
||||
finalizedBlockNumberAndHash,
|
||||
rollupForkChoiceUpdatedClients.size
|
||||
rollupForkChoiceUpdatedClients.size,
|
||||
)
|
||||
val futures: List<SafeFuture<*>> = rollupForkChoiceUpdatedClients.map { rollupForkChoiceUpdatedClient ->
|
||||
rollupForkChoiceUpdatedClient
|
||||
|
||||
@@ -28,7 +28,7 @@ class L1BasedLastFinalizedBlockProviderTest {
|
||||
whenever(lineaRollupClient.finalizedL2BlockNumber(eq(BlockParameter.Tag.LATEST)))
|
||||
.thenReturn(
|
||||
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(
|
||||
@@ -36,7 +36,7 @@ class L1BasedLastFinalizedBlockProviderTest {
|
||||
lineaRollupClient,
|
||||
consistentNumberOfBlocksOnL1 = 3u,
|
||||
numberOfRetries = 50u,
|
||||
pollingInterval = 10.milliseconds
|
||||
pollingInterval = 10.milliseconds,
|
||||
)
|
||||
|
||||
assertThat(resumerCalculator.getLastFinalizedBlock().get()).isEqualTo(101.toULong())
|
||||
|
||||
@@ -23,7 +23,7 @@ class L1DependentAppTest {
|
||||
val lastProcessedBlock =
|
||||
L1DependentApp.resumeConflationFrom(
|
||||
aggregationsRepository,
|
||||
lastFinalizedBlock
|
||||
lastFinalizedBlock,
|
||||
).get()
|
||||
assertThat(lastProcessedBlock).isEqualTo(lastFinalizedBlock)
|
||||
verify(aggregationsRepository).findConsecutiveProvenBlobs(lastFinalizedBlock.toLong() + 1)
|
||||
@@ -49,12 +49,12 @@ class L1DependentAppTest {
|
||||
lastConsecutiveAggregatedBlockNumber = lastConsecutiveAggregatedBlockNumber,
|
||||
batchesRepository = batchesRepository,
|
||||
blobsRepository = blobsRepository,
|
||||
aggregationsRepository = aggregationsRepository
|
||||
aggregationsRepository = aggregationsRepository,
|
||||
).get()
|
||||
verify(batchesRepository).deleteBatchesAfterBlockNumber((lastProcessedBlock + 1uL).toLong())
|
||||
verify(blobsRepository).deleteBlobsAfterBlockNumber(lastProcessedBlock + 1uL)
|
||||
verify(aggregationsRepository).deleteAggregationsAfterBlockNumber(
|
||||
(lastConsecutiveAggregatedBlockNumber + 1uL).toLong()
|
||||
(lastConsecutiveAggregatedBlockNumber + 1uL).toLong(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,9 +45,9 @@ class CoordinatorConfigTest {
|
||||
_smartContractErrors = mapOf(
|
||||
// L1 Linea Rollup
|
||||
"0f06cd15" to "DataAlreadySubmitted",
|
||||
"c01eab56" to "EmptySubmissionData"
|
||||
"c01eab56" to "EmptySubmissionData",
|
||||
),
|
||||
fetchBlocksLimit = 4000
|
||||
fetchBlocksLimit = 4000,
|
||||
)
|
||||
|
||||
private val proversConfig = ProversConfig(
|
||||
@@ -58,7 +58,7 @@ class CoordinatorConfigTest {
|
||||
pollingInterval = 1.seconds,
|
||||
pollingTimeout = 10.minutes,
|
||||
inprogressProvingSuffixPattern = ".*\\.inprogress\\.prover.*",
|
||||
inprogressRequestWritingSuffix = ".inprogress_coordinator_writing"
|
||||
inprogressRequestWritingSuffix = ".inprogress_coordinator_writing",
|
||||
),
|
||||
blobCompression = FileBasedProverConfig(
|
||||
requestsDirectory = Path.of("/data/prover/v2/compression/requests"),
|
||||
@@ -66,7 +66,7 @@ class CoordinatorConfigTest {
|
||||
pollingInterval = 1.seconds,
|
||||
pollingTimeout = 10.minutes,
|
||||
inprogressProvingSuffixPattern = ".*\\.inprogress\\.prover.*",
|
||||
inprogressRequestWritingSuffix = ".inprogress_coordinator_writing"
|
||||
inprogressRequestWritingSuffix = ".inprogress_coordinator_writing",
|
||||
),
|
||||
proofAggregation = FileBasedProverConfig(
|
||||
requestsDirectory = Path.of("/data/prover/v2/aggregation/requests"),
|
||||
@@ -74,24 +74,24 @@ class CoordinatorConfigTest {
|
||||
pollingInterval = 1.seconds,
|
||||
pollingTimeout = 10.minutes,
|
||||
inprogressProvingSuffixPattern = ".*\\.inprogress\\.prover.*",
|
||||
inprogressRequestWritingSuffix = ".inprogress_coordinator_writing"
|
||||
)
|
||||
inprogressRequestWritingSuffix = ".inprogress_coordinator_writing",
|
||||
),
|
||||
),
|
||||
switchBlockNumberInclusive = null,
|
||||
proverB = null
|
||||
proverB = null,
|
||||
)
|
||||
|
||||
private val blobCompressionConfig = BlobCompressionConfig(
|
||||
blobSizeLimit = 100 * 1024,
|
||||
handlerPollingInterval = Duration.parse("PT1S"),
|
||||
_batchesLimit = 1
|
||||
_batchesLimit = 1,
|
||||
)
|
||||
|
||||
private val aggregationConfig = AggregationConfig(
|
||||
aggregationProofsLimit = 3,
|
||||
aggregationDeadline = Duration.parse("PT10S"),
|
||||
aggregationCoordinatorPollingInterval = Duration.parse("PT2S"),
|
||||
deadlineCheckInterval = Duration.parse("PT8S")
|
||||
deadlineCheckInterval = Duration.parse("PT8S"),
|
||||
)
|
||||
|
||||
private val tracesConfig = TracesConfig(
|
||||
@@ -103,38 +103,38 @@ class CoordinatorConfigTest {
|
||||
requestLimitPerEndpoint = 1U,
|
||||
requestRetry = RequestRetryConfigTomlFriendly(
|
||||
backoffDelay = Duration.parse("PT1S"),
|
||||
failuresWarningThreshold = 2
|
||||
)
|
||||
failuresWarningThreshold = 2,
|
||||
),
|
||||
),
|
||||
countersV2 = TracesConfig.FunctionalityEndpoint(
|
||||
endpoints = listOf(URI("http://traces-node:8545/").toURL()),
|
||||
requestLimitPerEndpoint = 1U,
|
||||
requestRetry = RequestRetryConfigTomlFriendly(
|
||||
backoffDelay = Duration.parse("PT1S"),
|
||||
failuresWarningThreshold = 2
|
||||
)
|
||||
)
|
||||
failuresWarningThreshold = 2,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
private val type2StateProofProviderConfig = Type2StateProofProviderConfig(
|
||||
endpoints = listOf(URI("http://shomei-frontend:8888/").toURL()),
|
||||
requestRetry = RequestRetryConfigTomlFriendly(
|
||||
backoffDelay = Duration.parse("PT1S"),
|
||||
failuresWarningThreshold = 2
|
||||
failuresWarningThreshold = 2,
|
||||
),
|
||||
l1QueryBlockTag = BlockParameter.Tag.SAFE,
|
||||
l1PollingInterval = Duration.parse("PT6S")
|
||||
l1PollingInterval = Duration.parse("PT6S"),
|
||||
)
|
||||
private val stateManagerConfig = StateManagerClientConfig(
|
||||
version = "2.3.0",
|
||||
endpoints = listOf(
|
||||
URI("http://shomei:8888/").toURL()
|
||||
URI("http://shomei:8888/").toURL(),
|
||||
),
|
||||
requestLimitPerEndpoint = 2U,
|
||||
requestRetry = RequestRetryConfigTomlFriendly(
|
||||
backoffDelay = Duration.parse("PT2S"),
|
||||
failuresWarningThreshold = 2
|
||||
)
|
||||
failuresWarningThreshold = 2,
|
||||
),
|
||||
)
|
||||
|
||||
private val blobSubmissionConfig = BlobSubmissionConfig(
|
||||
@@ -146,7 +146,7 @@ class CoordinatorConfigTest {
|
||||
proofSubmissionDelay = Duration.parse("PT1S"),
|
||||
targetBlobsToSendPerTransaction = 9,
|
||||
useEthEstimateGas = false,
|
||||
disabled = false
|
||||
disabled = false,
|
||||
)
|
||||
|
||||
private val aggregationFinalizationConfig = AggregationFinalizationConfig(
|
||||
@@ -154,7 +154,7 @@ class CoordinatorConfigTest {
|
||||
maxAggregationsToFinalizePerTick = 1,
|
||||
proofSubmissionDelay = Duration.parse("PT1S"),
|
||||
useEthEstimateGas = true,
|
||||
disabled = false
|
||||
disabled = false,
|
||||
)
|
||||
|
||||
private val databaseConfig = DatabaseConfig(
|
||||
@@ -165,12 +165,12 @@ class CoordinatorConfigTest {
|
||||
schema = "linea_coordinator",
|
||||
readPoolSize = 10,
|
||||
readPipeliningLimit = 10,
|
||||
transactionalPoolSize = 10
|
||||
transactionalPoolSize = 10,
|
||||
)
|
||||
|
||||
private val persistenceRetryConfig = PersistenceRetryConfig(
|
||||
maxRetries = null,
|
||||
backoffDelay = Duration.parse("PT1S")
|
||||
backoffDelay = Duration.parse("PT1S"),
|
||||
)
|
||||
|
||||
private val l1Config = L1Config(
|
||||
@@ -194,7 +194,7 @@ class CoordinatorConfigTest {
|
||||
blockRangeLoopLimit = 500U,
|
||||
_ethFeeHistoryEndpoint = null,
|
||||
_genesisStateRootHash = "0x072ead6777750dc20232d1cee8dc9a395c2d350df4bbaa5096c6f59b214dcecd",
|
||||
_genesisShnarfV6 = "0x47452a1b9ebadfe02bdd02f580fa1eba17680d57eec968a591644d05d78ee84f"
|
||||
_genesisShnarfV6 = "0x47452a1b9ebadfe02bdd02f580fa1eba17680d57eec968a591644d05d78ee84f",
|
||||
)
|
||||
|
||||
private val l2Config = L2Config(
|
||||
@@ -208,7 +208,7 @@ class CoordinatorConfigTest {
|
||||
lastHashSearchWindow = 25U,
|
||||
anchoringReceiptPollingInterval = Duration.parse("PT01S"),
|
||||
maxReceiptRetries = 120U,
|
||||
newBlockPollingInterval = Duration.parse("PT1S")
|
||||
newBlockPollingInterval = Duration.parse("PT1S"),
|
||||
)
|
||||
|
||||
private val finalizationSigner = SignerConfig(
|
||||
@@ -219,9 +219,9 @@ class CoordinatorConfigTest {
|
||||
keepAlive = true,
|
||||
publicKey =
|
||||
"ba5734d8f7091719471e7f7ed6b9df170dc70cc661ca05e688601ad984f068b0d67351e5f06073092499336ab0839ef8a521afd334e5" +
|
||||
"3807205fa2f08eec74f4"
|
||||
"3807205fa2f08eec74f4",
|
||||
),
|
||||
web3j = Web3jConfig(Masked("0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"))
|
||||
web3j = Web3jConfig(Masked("0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d")),
|
||||
)
|
||||
|
||||
private val dataSubmissionSigner = SignerConfig(
|
||||
@@ -232,9 +232,9 @@ class CoordinatorConfigTest {
|
||||
keepAlive = true,
|
||||
publicKey =
|
||||
"9d9031e97dd78ff8c15aa86939de9b1e791066a0224e331bc962a2099a7b1f0464b8bbafe1535f2301c72c2cb3535b172da30b02686a" +
|
||||
"b0393d348614f157fbdb"
|
||||
"b0393d348614f157fbdb",
|
||||
),
|
||||
web3j = Web3jConfig(Masked("0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a"))
|
||||
web3j = Web3jConfig(Masked("0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a")),
|
||||
)
|
||||
private val l2SignerConfig = SignerConfig(
|
||||
type = SignerConfig.Type.Web3j,
|
||||
@@ -244,43 +244,43 @@ class CoordinatorConfigTest {
|
||||
keepAlive = true,
|
||||
publicKey =
|
||||
"4a788ad6fa008beed58de6418369717d7492f37d173d70e2c26d9737e2c6eeae929452ef8602a19410844db3e200a0e73f5208fd7625" +
|
||||
"9a8766b73953fc3e7023"
|
||||
"9a8766b73953fc3e7023",
|
||||
),
|
||||
web3j = Web3jConfig(Masked("0x4d01ae6487860981699236a58b68f807ee5f17b12df5740b85cf4c4653be0f55"))
|
||||
web3j = Web3jConfig(Masked("0x4d01ae6487860981699236a58b68f807ee5f17b12df5740b85cf4c4653be0f55")),
|
||||
)
|
||||
|
||||
private val l2NetworkGasPricingRequestRetryConfig = RequestRetryConfig(
|
||||
maxRetries = 3u,
|
||||
timeout = 6.seconds,
|
||||
backoffDelay = 1.seconds,
|
||||
failuresWarningThreshold = 2u
|
||||
failuresWarningThreshold = 2u,
|
||||
)
|
||||
|
||||
private val l2NetworkGasPricingServiceConfig = L2NetworkGasPricingService.Config(
|
||||
feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config(
|
||||
feeHistoryBlockCount = 50U,
|
||||
feeHistoryRewardPercentile = 15.0
|
||||
feeHistoryRewardPercentile = 15.0,
|
||||
),
|
||||
legacy = L2NetworkGasPricingService.LegacyGasPricingCalculatorConfig(
|
||||
legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config(
|
||||
feeUpperBound = 10_000_000_000.0,
|
||||
feeLowerBound = 90_000_000.0,
|
||||
feeMargin = 0.0
|
||||
feeMargin = 0.0,
|
||||
),
|
||||
transactionCostCalculatorConfig = TransactionCostCalculator.Config(
|
||||
sampleTransactionCostMultiplier = 1.0,
|
||||
fixedCostWei = 3000000u,
|
||||
compressedTxSize = 125,
|
||||
expectedGas = 21000
|
||||
expectedGas = 21000,
|
||||
),
|
||||
naiveGasPricingCalculatorConfig = null
|
||||
naiveGasPricingCalculatorConfig = null,
|
||||
),
|
||||
jsonRpcGasPriceUpdaterConfig = GasPriceUpdaterImpl.Config(
|
||||
gethEndpoints = listOf(
|
||||
URI("http://l2-node:8545/").toURL()
|
||||
URI("http://l2-node:8545/").toURL(),
|
||||
),
|
||||
besuEndPoints = listOf(),
|
||||
retryConfig = l2NetworkGasPricingRequestRetryConfig
|
||||
retryConfig = l2NetworkGasPricingRequestRetryConfig,
|
||||
),
|
||||
jsonRpcPriceUpdateInterval = 12.seconds,
|
||||
extraDataPricingPropagationEnabled = true,
|
||||
@@ -289,21 +289,21 @@ class CoordinatorConfigTest {
|
||||
blobSubmissionExpectedExecutionGas = 213_000u,
|
||||
bytesPerDataSubmission = 131072u,
|
||||
expectedBlobGas = 131072u,
|
||||
margin = 4.0
|
||||
margin = 4.0,
|
||||
),
|
||||
variableFeesCalculatorBounds = BoundableFeeCalculator.Config(
|
||||
feeUpperBound = 10_000_000_001.0,
|
||||
feeLowerBound = 90_000_001.0,
|
||||
feeMargin = 0.0
|
||||
feeMargin = 0.0,
|
||||
),
|
||||
extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config(
|
||||
fixedCostInKWei = 3000u,
|
||||
ethGasPriceMultiplier = 1.2
|
||||
ethGasPriceMultiplier = 1.2,
|
||||
),
|
||||
extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config(
|
||||
sequencerEndpoint = URI(/* str = */ "http://sequencer:8545/").toURL(),
|
||||
retryConfig = l2NetworkGasPricingRequestRetryConfig
|
||||
)
|
||||
sequencerEndpoint = URI("http://sequencer:8545/").toURL(),
|
||||
retryConfig = l2NetworkGasPricingRequestRetryConfig,
|
||||
),
|
||||
)
|
||||
|
||||
private val l1DynamicGasPriceCapServiceConfig = L1DynamicGasPriceCapServiceConfig(
|
||||
@@ -318,18 +318,18 @@ class CoordinatorConfigTest {
|
||||
gasPriceCapsCheckCoefficient = 0.9,
|
||||
historicBaseFeePerBlobGasLowerBound = 100_000_000u,
|
||||
historicAvgRewardConstant = 100_000_000u,
|
||||
timeOfDayMultipliers = expectedTimeOfDayMultipliers
|
||||
timeOfDayMultipliers = expectedTimeOfDayMultipliers,
|
||||
),
|
||||
feeHistoryFetcher = L1DynamicGasPriceCapServiceConfig.FeeHistoryFetcher(
|
||||
fetchInterval = Duration.parse("PT1S"),
|
||||
maxBlockCount = 1000U,
|
||||
rewardPercentiles = listOf(10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0),
|
||||
numOfBlocksBeforeLatest = 4U,
|
||||
endpoint = null
|
||||
endpoint = null,
|
||||
),
|
||||
feeHistoryStorage = L1DynamicGasPriceCapServiceConfig.FeeHistoryStorage(
|
||||
storagePeriod = Duration.parse("PT2M")
|
||||
)
|
||||
storagePeriod = Duration.parse("PT2M"),
|
||||
),
|
||||
)
|
||||
|
||||
private val coordinatorConfig = CoordinatorConfig(
|
||||
@@ -351,11 +351,11 @@ class CoordinatorConfigTest {
|
||||
l2Signer = l2SignerConfig,
|
||||
messageAnchoring = MessageAnchoringConfigTomlDto().reified(
|
||||
l1DefaultEndpoint = l1Config.rpcEndpoint,
|
||||
l2DefaultEndpoint = l2Config.rpcEndpoint
|
||||
l2DefaultEndpoint = l2Config.rpcEndpoint,
|
||||
),
|
||||
l2NetworkGasPricingService = l2NetworkGasPricingServiceConfig,
|
||||
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-web3signer-override.config.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"),
|
||||
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 {
|
||||
return Paths.get(
|
||||
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")),
|
||||
tracesLimitsFileV2 = pathToResource("configs/traces-limits-v2.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)
|
||||
@@ -404,18 +404,18 @@ class CoordinatorConfigTest {
|
||||
val config = loadConfigs(
|
||||
coordinatorConfigFiles = listOf(
|
||||
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"),
|
||||
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 =
|
||||
coordinatorConfig.copy(
|
||||
finalizationSigner = finalizationSigner.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)
|
||||
@@ -426,11 +426,11 @@ class CoordinatorConfigTest {
|
||||
val config = loadConfigs(
|
||||
coordinatorConfigFiles = listOf(
|
||||
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"),
|
||||
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 =
|
||||
@@ -441,31 +441,31 @@ class CoordinatorConfigTest {
|
||||
transactionCostCalculatorConfig =
|
||||
l2NetworkGasPricingServiceConfig.legacy.transactionCostCalculatorConfig?.copy(
|
||||
compressedTxSize = 350,
|
||||
expectedGas = 29400
|
||||
)
|
||||
)
|
||||
expectedGas = 29400,
|
||||
),
|
||||
),
|
||||
),
|
||||
traces = tracesConfig.copy(
|
||||
blobCompressorVersion = BlobCompressorVersion.V1_2,
|
||||
expectedTracesApiVersionV2 = "v0.8.0-rc8",
|
||||
conflationV2 = tracesConfig.conflationV2,
|
||||
countersV2 = tracesConfig.countersV2
|
||||
countersV2 = tracesConfig.countersV2,
|
||||
),
|
||||
proversConfig = proversConfig.copy(
|
||||
proverA = proversConfig.proverA.copy(
|
||||
execution = proversConfig.proverA.execution.copy(
|
||||
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(
|
||||
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(
|
||||
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(
|
||||
l1Endpoint = URI("http://l1-endpoint-for-anchoring:8545").toURL(),
|
||||
@@ -475,12 +475,12 @@ class CoordinatorConfigTest {
|
||||
anchoringTickInterval = 1.seconds.toJavaDuration(),
|
||||
l1RequestRetries = RequestRetryConfigTomlFriendly(
|
||||
maxRetries = 10,
|
||||
failuresWarningThreshold = 1
|
||||
)
|
||||
failuresWarningThreshold = 1,
|
||||
),
|
||||
).reified(
|
||||
l1DefaultEndpoint = l1Config.rpcEndpoint,
|
||||
l2DefaultEndpoint = l2Config.rpcEndpoint
|
||||
)
|
||||
l2DefaultEndpoint = l2Config.rpcEndpoint,
|
||||
),
|
||||
)
|
||||
|
||||
assertThat(config).isEqualTo(expectedConfig)
|
||||
@@ -489,7 +489,7 @@ class CoordinatorConfigTest {
|
||||
@Test
|
||||
fun invalidConfigReturnsErrorResult() {
|
||||
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")
|
||||
@@ -498,17 +498,17 @@ class CoordinatorConfigTest {
|
||||
@Test
|
||||
fun testInvalidAggregationByTargetBlockNumberWhenL2InclusiveBlockNumberToStopAndFlushAggregationSpecified() {
|
||||
val aggregationConfigWithoutTargetBlockNumber = aggregationConfig.copy(
|
||||
_targetEndBlocks = emptyList()
|
||||
_targetEndBlocks = emptyList(),
|
||||
)
|
||||
val conflationConfigWithTargetBlockNumber = conflationConfig.copy(
|
||||
_conflationTargetEndBlockNumbers = listOf(100L)
|
||||
_conflationTargetEndBlockNumbers = listOf(100L),
|
||||
)
|
||||
|
||||
val exception = assertThrows<IllegalArgumentException> {
|
||||
coordinatorConfig.copy(
|
||||
l2InclusiveBlockNumberToStopAndFlushAggregation = 100uL,
|
||||
proofAggregation = aggregationConfigWithoutTargetBlockNumber,
|
||||
conflation = conflationConfigWithTargetBlockNumber
|
||||
conflation = conflationConfigWithTargetBlockNumber,
|
||||
)
|
||||
}
|
||||
assertThat(exception.message)
|
||||
@@ -518,40 +518,40 @@ class CoordinatorConfigTest {
|
||||
@Test
|
||||
fun testInvalidConflationByTargetBlockNumberWhenL2InclusiveBlockNumberToStopAndFlushAggregationSpecified() {
|
||||
val aggregationConfigWithTargetBlockNumber = aggregationConfig.copy(
|
||||
_targetEndBlocks = listOf(100L)
|
||||
_targetEndBlocks = listOf(100L),
|
||||
)
|
||||
val conflationConfigWithoutTargetBlockNumber = conflationConfig.copy(
|
||||
_conflationTargetEndBlockNumbers = emptyList()
|
||||
_conflationTargetEndBlockNumbers = emptyList(),
|
||||
)
|
||||
|
||||
val exception = assertThrows<IllegalArgumentException> {
|
||||
coordinatorConfig.copy(
|
||||
l2InclusiveBlockNumberToStopAndFlushAggregation = 100uL,
|
||||
proofAggregation = aggregationConfigWithTargetBlockNumber,
|
||||
conflation = conflationConfigWithoutTargetBlockNumber
|
||||
conflation = conflationConfigWithoutTargetBlockNumber,
|
||||
)
|
||||
}
|
||||
assertThat(exception.message)
|
||||
.isEqualTo(
|
||||
"conflation.conflationTargetEndBlockNumbers should contain the " +
|
||||
"l2InclusiveBlockNumberToStopAndFlushAggregation"
|
||||
"l2InclusiveBlockNumberToStopAndFlushAggregation",
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testValidAggrAndConflationByTargetBlockNumberWhenL2InclusiveBlockNumberToStopAndFlushAggregationSpecified() {
|
||||
val aggregationConfigWithoutSwithBlockNumber = aggregationConfig.copy(
|
||||
_targetEndBlocks = listOf(10L, 100L)
|
||||
_targetEndBlocks = listOf(10L, 100L),
|
||||
)
|
||||
val conflationConfigWithTargetBlockNumber = conflationConfig.copy(
|
||||
_conflationTargetEndBlockNumbers = listOf(100L)
|
||||
_conflationTargetEndBlockNumbers = listOf(100L),
|
||||
)
|
||||
|
||||
assertDoesNotThrow {
|
||||
coordinatorConfig.copy(
|
||||
l2InclusiveBlockNumberToStopAndFlushAggregation = 100uL,
|
||||
proofAggregation = aggregationConfigWithoutSwithBlockNumber,
|
||||
conflation = conflationConfigWithTargetBlockNumber
|
||||
conflation = conflationConfigWithTargetBlockNumber,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,5 +168,5 @@ val expectedTimeOfDayMultipliers = mapOf(
|
||||
"SATURDAY_20" to 1.5073787902995706,
|
||||
"SATURDAY_21" to 1.5605139580010123,
|
||||
"SATURDAY_22" to 1.5885303316932382,
|
||||
"SATURDAY_23" to 1.6169891066719597
|
||||
"SATURDAY_23" to 1.6169891066719597,
|
||||
)
|
||||
|
||||
@@ -55,6 +55,6 @@ val expectedTracesLimitsV2 = TracesCountersV2(
|
||||
TracingModuleV2.BLOCK_KECCAK to 46u,
|
||||
TracingModuleV2.BLOCK_L1_SIZE to 47u,
|
||||
TracingModuleV2.BLOCK_L2_L1_LOGS to 48u,
|
||||
TracingModuleV2.BLOCK_TRANSACTIONS to 49u
|
||||
)
|
||||
TracingModuleV2.BLOCK_TRANSACTIONS to 49u,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -21,7 +21,7 @@ import kotlin.time.toJavaDuration
|
||||
|
||||
class L2NetworkGasPricingConfigTest {
|
||||
data class Config(
|
||||
val l2NetworkGasPricing: L2NetworkGasPricingTomlDto
|
||||
val l2NetworkGasPricing: L2NetworkGasPricingTomlDto,
|
||||
)
|
||||
|
||||
private fun parseConfig(toml: String): L2NetworkGasPricingTomlDto {
|
||||
@@ -135,7 +135,7 @@ class L2NetworkGasPricingConfigTest {
|
||||
maxRetries = 3,
|
||||
timeout = 6.seconds.toJavaDuration(),
|
||||
backoffDelay = 1.seconds.toJavaDuration(),
|
||||
failuresWarningThreshold = 2
|
||||
failuresWarningThreshold = 2,
|
||||
),
|
||||
|
||||
priceUpdateInterval = Duration.parse("PT12S"),
|
||||
@@ -152,29 +152,29 @@ class L2NetworkGasPricingConfigTest {
|
||||
naiveGasPricing = NaiveGasPricingTomlDto(
|
||||
baseFeeCoefficient = 0.1,
|
||||
priorityFeeCoefficient = 1.0,
|
||||
baseFeeBlobCoefficient = 0.1
|
||||
)
|
||||
baseFeeBlobCoefficient = 0.1,
|
||||
),
|
||||
),
|
||||
variableCostPricing = VariableCostPricingTomlDto(
|
||||
gasPriceFixedCost = 3000000u,
|
||||
legacyFeesMultiplier = 1.2,
|
||||
margin = 4.0,
|
||||
variableCostUpperBound = 10_000_000_001u,
|
||||
variableCostLowerBound = 90_000_001u
|
||||
variableCostLowerBound = 90_000_001u,
|
||||
),
|
||||
jsonRpcPricingPropagation = JsonRpcPricingPropagationTomlDto(
|
||||
gethGasPriceUpdateRecipients = listOf(
|
||||
URI("http://traces-node:8545/").toURL(),
|
||||
URI("http://l2-node:8545/").toURL()
|
||||
URI("http://l2-node:8545/").toURL(),
|
||||
),
|
||||
besuGasPriceUpdateRecipients = listOf(
|
||||
URI("http://sequencer:8545/").toURL()
|
||||
)
|
||||
URI("http://sequencer:8545/").toURL(),
|
||||
),
|
||||
),
|
||||
extraDataPricingPropagation = ExtraDataPricingPropagationTomlDto(
|
||||
extraDataUpdateRecipient = URI("http://sequencer:8545/").toURL()
|
||||
)
|
||||
)
|
||||
extraDataUpdateRecipient = URI("http://sequencer:8545/").toURL(),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ class L2NetworkGasPricingConfigTest {
|
||||
maxRetries = 3,
|
||||
timeout = 6.seconds.toJavaDuration(),
|
||||
backoffDelay = 1.seconds.toJavaDuration(),
|
||||
failuresWarningThreshold = 2
|
||||
failuresWarningThreshold = 2,
|
||||
),
|
||||
|
||||
priceUpdateInterval = Duration.parse("PT12S"),
|
||||
@@ -201,28 +201,28 @@ class L2NetworkGasPricingConfigTest {
|
||||
type = LegacyGasPricingTomlDto.Type.SampleTransaction,
|
||||
gasPriceUpperBound = 10_000_000_000u,
|
||||
gasPriceLowerBound = 90_000_000u,
|
||||
naiveGasPricing = null
|
||||
naiveGasPricing = null,
|
||||
),
|
||||
variableCostPricing = VariableCostPricingTomlDto(
|
||||
gasPriceFixedCost = 3000000u,
|
||||
legacyFeesMultiplier = 1.2,
|
||||
margin = 4.0,
|
||||
variableCostUpperBound = 10_000_000_001u,
|
||||
variableCostLowerBound = 90_000_001u
|
||||
variableCostLowerBound = 90_000_001u,
|
||||
),
|
||||
jsonRpcPricingPropagation = JsonRpcPricingPropagationTomlDto(
|
||||
gethGasPriceUpdateRecipients = listOf(
|
||||
URI("http://traces-node:8545/").toURL(),
|
||||
URI("http://l2-node:8545/").toURL()
|
||||
URI("http://l2-node:8545/").toURL(),
|
||||
),
|
||||
besuGasPriceUpdateRecipients = listOf(
|
||||
URI("http://sequencer:8545/").toURL()
|
||||
)
|
||||
URI("http://sequencer:8545/").toURL(),
|
||||
),
|
||||
),
|
||||
extraDataPricingPropagation = ExtraDataPricingPropagationTomlDto(
|
||||
extraDataUpdateRecipient = URI("http://sequencer:8545/").toURL()
|
||||
)
|
||||
)
|
||||
extraDataUpdateRecipient = URI("http://sequencer:8545/").toURL(),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -233,14 +233,14 @@ class L2NetworkGasPricingConfigTest {
|
||||
maxRetries = 3u,
|
||||
timeout = 6.seconds,
|
||||
backoffDelay = 1.seconds,
|
||||
failuresWarningThreshold = 2u
|
||||
failuresWarningThreshold = 2u,
|
||||
)
|
||||
|
||||
assertThat(config).isEqualTo(
|
||||
L2NetworkGasPricingService.Config(
|
||||
feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config(
|
||||
feeHistoryBlockCount = 50U,
|
||||
feeHistoryRewardPercentile = 15.0
|
||||
feeHistoryRewardPercentile = 15.0,
|
||||
),
|
||||
legacy = L2NetworkGasPricingService.LegacyGasPricingCalculatorConfig(
|
||||
naiveGasPricingCalculatorConfig = GasUsageRatioWeightedAverageFeesCalculator.Config(
|
||||
@@ -248,24 +248,24 @@ class L2NetworkGasPricingConfigTest {
|
||||
priorityFeeCoefficient = 1.0,
|
||||
baseFeeBlobCoefficient = 0.1,
|
||||
blobSubmissionExpectedExecutionGas = 213_000,
|
||||
expectedBlobGas = 131072
|
||||
expectedBlobGas = 131072,
|
||||
),
|
||||
legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config(
|
||||
10_000_000_000.0,
|
||||
90_000_000.0,
|
||||
0.0
|
||||
0.0,
|
||||
),
|
||||
transactionCostCalculatorConfig = null
|
||||
transactionCostCalculatorConfig = null,
|
||||
),
|
||||
jsonRpcGasPriceUpdaterConfig = GasPriceUpdaterImpl.Config(
|
||||
gethEndpoints = listOf(
|
||||
URI("http://traces-node:8545/").toURL(),
|
||||
URI("http://l2-node:8545/").toURL()
|
||||
URI("http://l2-node:8545/").toURL(),
|
||||
),
|
||||
besuEndPoints = listOf(
|
||||
URI("http://sequencer:8545/").toURL()
|
||||
URI("http://sequencer:8545/").toURL(),
|
||||
),
|
||||
retryConfig = l2NetworkGasPricingRequestretryConfig
|
||||
retryConfig = l2NetworkGasPricingRequestretryConfig,
|
||||
),
|
||||
jsonRpcPriceUpdateInterval = 12.seconds,
|
||||
extraDataPricingPropagationEnabled = true,
|
||||
@@ -274,22 +274,22 @@ class L2NetworkGasPricingConfigTest {
|
||||
blobSubmissionExpectedExecutionGas = 213_000u,
|
||||
bytesPerDataSubmission = 131072u,
|
||||
expectedBlobGas = 131072u,
|
||||
margin = 4.0
|
||||
margin = 4.0,
|
||||
),
|
||||
variableFeesCalculatorBounds = BoundableFeeCalculator.Config(
|
||||
feeUpperBound = 10_000_000_001.0,
|
||||
feeLowerBound = 90_000_001.0,
|
||||
feeMargin = 0.0
|
||||
feeMargin = 0.0,
|
||||
),
|
||||
extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config(
|
||||
fixedCostInKWei = 3000u,
|
||||
ethGasPriceMultiplier = 1.2
|
||||
ethGasPriceMultiplier = 1.2,
|
||||
),
|
||||
extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config(
|
||||
sequencerEndpoint = URI(/* str = */ "http://sequencer:8545/").toURL(),
|
||||
retryConfig = l2NetworkGasPricingRequestretryConfig
|
||||
)
|
||||
)
|
||||
sequencerEndpoint = URI("http://sequencer:8545/").toURL(),
|
||||
retryConfig = l2NetworkGasPricingRequestretryConfig,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -300,38 +300,38 @@ class L2NetworkGasPricingConfigTest {
|
||||
maxRetries = 3u,
|
||||
timeout = 6.seconds,
|
||||
backoffDelay = 1.seconds,
|
||||
failuresWarningThreshold = 2u
|
||||
failuresWarningThreshold = 2u,
|
||||
)
|
||||
|
||||
assertThat(config).isEqualTo(
|
||||
L2NetworkGasPricingService.Config(
|
||||
feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config(
|
||||
feeHistoryBlockCount = 50U,
|
||||
feeHistoryRewardPercentile = 15.0
|
||||
feeHistoryRewardPercentile = 15.0,
|
||||
),
|
||||
legacy = L2NetworkGasPricingService.LegacyGasPricingCalculatorConfig(
|
||||
naiveGasPricingCalculatorConfig = null,
|
||||
legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config(
|
||||
10_000_000_000.0,
|
||||
90_000_000.0,
|
||||
0.0
|
||||
0.0,
|
||||
),
|
||||
transactionCostCalculatorConfig = TransactionCostCalculator.Config(
|
||||
sampleTransactionCostMultiplier = 1.0,
|
||||
fixedCostWei = 3000000u,
|
||||
compressedTxSize = 125,
|
||||
expectedGas = 21000
|
||||
)
|
||||
expectedGas = 21000,
|
||||
),
|
||||
),
|
||||
jsonRpcGasPriceUpdaterConfig = GasPriceUpdaterImpl.Config(
|
||||
gethEndpoints = listOf(
|
||||
URI("http://traces-node:8545/").toURL(),
|
||||
URI("http://l2-node:8545/").toURL()
|
||||
URI("http://l2-node:8545/").toURL(),
|
||||
),
|
||||
besuEndPoints = listOf(
|
||||
URI("http://sequencer:8545/").toURL()
|
||||
URI("http://sequencer:8545/").toURL(),
|
||||
),
|
||||
retryConfig = l2NetworkGasPricingRequestretryConfig
|
||||
retryConfig = l2NetworkGasPricingRequestretryConfig,
|
||||
),
|
||||
jsonRpcPriceUpdateInterval = 12.seconds,
|
||||
extraDataPricingPropagationEnabled = true,
|
||||
@@ -340,22 +340,22 @@ class L2NetworkGasPricingConfigTest {
|
||||
blobSubmissionExpectedExecutionGas = 213_000u,
|
||||
bytesPerDataSubmission = 131072u,
|
||||
expectedBlobGas = 131072u,
|
||||
margin = 4.0
|
||||
margin = 4.0,
|
||||
),
|
||||
variableFeesCalculatorBounds = BoundableFeeCalculator.Config(
|
||||
feeUpperBound = 10_000_000_001.0,
|
||||
feeLowerBound = 90_000_001.0,
|
||||
feeMargin = 0.0
|
||||
feeMargin = 0.0,
|
||||
),
|
||||
extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config(
|
||||
fixedCostInKWei = 3000u,
|
||||
ethGasPriceMultiplier = 1.2
|
||||
ethGasPriceMultiplier = 1.2,
|
||||
),
|
||||
extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config(
|
||||
sequencerEndpoint = URI(/* str = */ "http://sequencer:8545/").toURL(),
|
||||
retryConfig = l2NetworkGasPricingRequestretryConfig
|
||||
)
|
||||
)
|
||||
sequencerEndpoint = URI("http://sequencer:8545/").toURL(),
|
||||
retryConfig = l2NetworkGasPricingRequestretryConfig,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -400,28 +400,28 @@ class L2NetworkGasPricingConfigTest {
|
||||
maxRetries = 3u,
|
||||
timeout = 6.seconds,
|
||||
backoffDelay = 1.seconds,
|
||||
failuresWarningThreshold = 2u
|
||||
failuresWarningThreshold = 2u,
|
||||
)
|
||||
|
||||
assertThat(config).isEqualTo(
|
||||
L2NetworkGasPricingService.Config(
|
||||
feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config(
|
||||
feeHistoryBlockCount = 50U,
|
||||
feeHistoryRewardPercentile = 15.0
|
||||
feeHistoryRewardPercentile = 15.0,
|
||||
),
|
||||
legacy = L2NetworkGasPricingService.LegacyGasPricingCalculatorConfig(
|
||||
naiveGasPricingCalculatorConfig = null,
|
||||
legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config(
|
||||
10_000_000_000.0,
|
||||
90_000_000.0,
|
||||
0.0
|
||||
0.0,
|
||||
),
|
||||
transactionCostCalculatorConfig = TransactionCostCalculator.Config(
|
||||
sampleTransactionCostMultiplier = 1.0,
|
||||
fixedCostWei = 3000000u,
|
||||
compressedTxSize = 125,
|
||||
expectedGas = 21000
|
||||
)
|
||||
expectedGas = 21000,
|
||||
),
|
||||
),
|
||||
jsonRpcGasPriceUpdaterConfig = null,
|
||||
jsonRpcPriceUpdateInterval = 12.seconds,
|
||||
@@ -431,22 +431,22 @@ class L2NetworkGasPricingConfigTest {
|
||||
blobSubmissionExpectedExecutionGas = 213_000u,
|
||||
bytesPerDataSubmission = 131072u,
|
||||
expectedBlobGas = 131072u,
|
||||
margin = 4.0
|
||||
margin = 4.0,
|
||||
),
|
||||
variableFeesCalculatorBounds = BoundableFeeCalculator.Config(
|
||||
feeUpperBound = 10_000_000_001.0,
|
||||
feeLowerBound = 90_000_001.0,
|
||||
feeMargin = 0.0
|
||||
feeMargin = 0.0,
|
||||
),
|
||||
extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config(
|
||||
fixedCostInKWei = 3000u,
|
||||
ethGasPriceMultiplier = 1.2
|
||||
ethGasPriceMultiplier = 1.2,
|
||||
),
|
||||
extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config(
|
||||
sequencerEndpoint = URI(/* str = */ "http://sequencer:8545/").toURL(),
|
||||
retryConfig = l2NetworkGasPricingRequestretryConfig
|
||||
)
|
||||
)
|
||||
sequencerEndpoint = URI("http://sequencer:8545/").toURL(),
|
||||
retryConfig = l2NetworkGasPricingRequestretryConfig,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -496,28 +496,28 @@ class L2NetworkGasPricingConfigTest {
|
||||
maxRetries = 3u,
|
||||
timeout = 6.seconds,
|
||||
backoffDelay = 1.seconds,
|
||||
failuresWarningThreshold = 2u
|
||||
failuresWarningThreshold = 2u,
|
||||
)
|
||||
|
||||
assertThat(config).isEqualTo(
|
||||
L2NetworkGasPricingService.Config(
|
||||
feeHistoryFetcherConfig = FeeHistoryFetcherImpl.Config(
|
||||
feeHistoryBlockCount = 50U,
|
||||
feeHistoryRewardPercentile = 15.0
|
||||
feeHistoryRewardPercentile = 15.0,
|
||||
),
|
||||
legacy = L2NetworkGasPricingService.LegacyGasPricingCalculatorConfig(
|
||||
naiveGasPricingCalculatorConfig = null,
|
||||
legacyGasPricingCalculatorBounds = BoundableFeeCalculator.Config(
|
||||
10_000_000_000.0,
|
||||
90_000_000.0,
|
||||
0.0
|
||||
0.0,
|
||||
),
|
||||
transactionCostCalculatorConfig = TransactionCostCalculator.Config(
|
||||
sampleTransactionCostMultiplier = 1.0,
|
||||
fixedCostWei = 3000000u,
|
||||
compressedTxSize = 125,
|
||||
expectedGas = 21000
|
||||
)
|
||||
expectedGas = 21000,
|
||||
),
|
||||
),
|
||||
jsonRpcGasPriceUpdaterConfig = null,
|
||||
jsonRpcPriceUpdateInterval = 12.seconds,
|
||||
@@ -527,22 +527,22 @@ class L2NetworkGasPricingConfigTest {
|
||||
blobSubmissionExpectedExecutionGas = 213_000u,
|
||||
bytesPerDataSubmission = 131072u,
|
||||
expectedBlobGas = 131072u,
|
||||
margin = 4.0
|
||||
margin = 4.0,
|
||||
),
|
||||
variableFeesCalculatorBounds = BoundableFeeCalculator.Config(
|
||||
feeUpperBound = 10_000_000_001.0,
|
||||
feeLowerBound = 90_000_001.0,
|
||||
feeMargin = 0.0
|
||||
feeMargin = 0.0,
|
||||
),
|
||||
extraDataCalculatorConfig = MinerExtraDataV1CalculatorImpl.Config(
|
||||
fixedCostInKWei = 3000u,
|
||||
ethGasPriceMultiplier = 1.2
|
||||
ethGasPriceMultiplier = 1.2,
|
||||
),
|
||||
extraDataUpdaterConfig = ExtraDataV1UpdaterImpl.Config(
|
||||
sequencerEndpoint = URI(/* str = */ "http://sequencer:8545/").toURL(),
|
||||
retryConfig = l2NetworkGasPricingRequestretryConfig
|
||||
)
|
||||
)
|
||||
sequencerEndpoint = URI("http://sequencer:8545/").toURL(),
|
||||
retryConfig = l2NetworkGasPricingRequestretryConfig,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ class MessageAnchoringConfigTest {
|
||||
private val l1DefaultEndpoint = URI("http://l1-default-rpc-endpoint:8545").toURL()
|
||||
private val l2DefaultEndpoint = URI("http://l2-default-rpc-endpoint:8545").toURL()
|
||||
data class Config(
|
||||
val messageAnchoring: MessageAnchoringConfigTomlDto = MessageAnchoringConfigTomlDto()
|
||||
val messageAnchoring: MessageAnchoringConfigTomlDto = MessageAnchoringConfigTomlDto(),
|
||||
)
|
||||
|
||||
private fun parseConfig(toml: String): MessageAnchoringConfig {
|
||||
@@ -27,7 +27,7 @@ class MessageAnchoringConfigTest {
|
||||
.let {
|
||||
it.messageAnchoring.reified(
|
||||
l1DefaultEndpoint = l1DefaultEndpoint,
|
||||
l2DefaultEndpoint = l2DefaultEndpoint
|
||||
l2DefaultEndpoint = l2DefaultEndpoint,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -74,13 +74,13 @@ class MessageAnchoringConfigTest {
|
||||
maxRetries = 10u,
|
||||
timeout = 100.seconds,
|
||||
backoffDelay = 11.seconds,
|
||||
failuresWarningThreshold = 1u
|
||||
failuresWarningThreshold = 1u,
|
||||
),
|
||||
l2RequestRetryConfig = RetryConfig(
|
||||
maxRetries = 20u,
|
||||
timeout = 200.seconds,
|
||||
backoffDelay = 21.seconds,
|
||||
failuresWarningThreshold = 2u
|
||||
failuresWarningThreshold = 2u,
|
||||
),
|
||||
l1EventPollingInterval = 30.seconds,
|
||||
l1EventPollingTimeout = 6.seconds,
|
||||
@@ -88,8 +88,8 @@ class MessageAnchoringConfigTest {
|
||||
l1EventSearchBlockChunk = 123u,
|
||||
anchoringTickInterval = 3.seconds,
|
||||
messageQueueCapacity = 321u,
|
||||
maxMessagesToAnchorPerL2Transaction = 54u
|
||||
)
|
||||
maxMessagesToAnchorPerL2Transaction = 54u,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -111,13 +111,13 @@ class MessageAnchoringConfigTest {
|
||||
maxRetries = null,
|
||||
timeout = null,
|
||||
backoffDelay = 1.seconds,
|
||||
failuresWarningThreshold = 3u
|
||||
failuresWarningThreshold = 3u,
|
||||
),
|
||||
l2RequestRetryConfig = RetryConfig(
|
||||
maxRetries = null,
|
||||
timeout = null,
|
||||
backoffDelay = 1.seconds,
|
||||
failuresWarningThreshold = 3u
|
||||
failuresWarningThreshold = 3u,
|
||||
),
|
||||
l1EventPollingInterval = 12.seconds,
|
||||
l1EventPollingTimeout = 6.seconds,
|
||||
@@ -125,8 +125,8 @@ class MessageAnchoringConfigTest {
|
||||
l1EventSearchBlockChunk = 1000u,
|
||||
anchoringTickInterval = 2.seconds,
|
||||
messageQueueCapacity = 10_000u,
|
||||
maxMessagesToAnchorPerL2Transaction = 100u
|
||||
)
|
||||
maxMessagesToAnchorPerL2Transaction = 100u,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
class ProverConfigTest {
|
||||
data class Config(
|
||||
val prover: ProverConfigTomlDto
|
||||
val prover: ProverConfigTomlDto,
|
||||
)
|
||||
|
||||
private fun parseConfig(toml: String): ProversConfig {
|
||||
@@ -62,8 +62,8 @@ class ProverConfigTest {
|
||||
inprogressRequestWritingSuffix = ".OVERRIDE_inprogress_coordinator_writing",
|
||||
inprogressProvingSuffixPattern = "OVERRIDE_\\.inprogress\\.prover.*",
|
||||
pollingInterval = 10.seconds,
|
||||
pollingTimeout = 10.minutes
|
||||
)
|
||||
pollingTimeout = 10.minutes,
|
||||
),
|
||||
)
|
||||
assertThat(config.blobCompression).isEqualTo(
|
||||
FileBasedProverConfig(
|
||||
@@ -72,8 +72,8 @@ class ProverConfigTest {
|
||||
inprogressRequestWritingSuffix = ".inprogress_coordinator_writing",
|
||||
inprogressProvingSuffixPattern = "\\.inprogress\\.prover.*",
|
||||
pollingInterval = 20.seconds,
|
||||
pollingTimeout = 20.minutes
|
||||
)
|
||||
pollingTimeout = 20.minutes,
|
||||
),
|
||||
)
|
||||
assertThat(config.proofAggregation).isEqualTo(
|
||||
FileBasedProverConfig(
|
||||
@@ -82,8 +82,8 @@ class ProverConfigTest {
|
||||
inprogressRequestWritingSuffix = ".inprogress_coordinator_writing",
|
||||
inprogressProvingSuffixPattern = "\\.inprogress\\.prover.*",
|
||||
pollingInterval = 10.seconds,
|
||||
pollingTimeout = 10.minutes
|
||||
)
|
||||
pollingTimeout = 10.minutes,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -122,8 +122,8 @@ class ProverConfigTest {
|
||||
inprogressRequestWritingSuffix = ".NEW_OVERRIDE_2_inprogress_coordinator_writing",
|
||||
inprogressProvingSuffixPattern = "NEW_OVERRIDE_2\\.inprogress\\.prover.*",
|
||||
pollingInterval = 10.seconds,
|
||||
pollingTimeout = 5.minutes
|
||||
)
|
||||
pollingTimeout = 5.minutes,
|
||||
),
|
||||
)
|
||||
assertThat(config.proverB!!.blobCompression).isEqualTo(
|
||||
FileBasedProverConfig(
|
||||
@@ -132,8 +132,8 @@ class ProverConfigTest {
|
||||
inprogressRequestWritingSuffix = ".NEW_OVERRIDE_inprogress_coordinator_writing",
|
||||
inprogressProvingSuffixPattern = "\\.inprogress\\.prover.*",
|
||||
pollingInterval = 12.seconds,
|
||||
pollingTimeout = 12.minutes
|
||||
)
|
||||
pollingTimeout = 12.minutes,
|
||||
),
|
||||
)
|
||||
assertThat(config.proverB!!.proofAggregation).isEqualTo(
|
||||
FileBasedProverConfig(
|
||||
@@ -142,8 +142,8 @@ class ProverConfigTest {
|
||||
inprogressRequestWritingSuffix = ".NEW_OVERRIDE_inprogress_coordinator_writing",
|
||||
inprogressProvingSuffixPattern = "\\.inprogress\\.prover.*",
|
||||
pollingInterval = 10.seconds,
|
||||
pollingTimeout = 5.minutes
|
||||
)
|
||||
pollingTimeout = 5.minutes,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ class BlockCreationMonitorTest {
|
||||
pollingInterval = 100.milliseconds,
|
||||
blocksToFinalization = 2L,
|
||||
blocksFetchLimit = 500,
|
||||
lastL2BlockNumberToProcessInclusive = null
|
||||
lastL2BlockNumberToProcessInclusive = null,
|
||||
)
|
||||
private lateinit var vertx: Vertx
|
||||
private lateinit var lastProvenBlockNumberProvider: LastProvenBlockNumberProviderDouble
|
||||
@@ -62,7 +62,7 @@ class BlockCreationMonitorTest {
|
||||
}
|
||||
|
||||
private class LastProvenBlockNumberProviderDouble(
|
||||
initialValue: ULong
|
||||
initialValue: ULong,
|
||||
) : LastProvenBlockNumberProviderAsync {
|
||||
var lastProvenBlock: AtomicLong = AtomicLong(initialValue.toLong())
|
||||
override fun getLastProvenBlockNumber(): SafeFuture<Long> {
|
||||
@@ -73,7 +73,7 @@ class BlockCreationMonitorTest {
|
||||
fun createBlockCreationMonitor(
|
||||
startingBlockNumberExclusive: Long = 99,
|
||||
blockCreationListener: BlockCreationListener = this.blockCreationListener,
|
||||
config: BlockCreationMonitor.Config = this.config
|
||||
config: BlockCreationMonitor.Config = this.config,
|
||||
): BlockCreationMonitor {
|
||||
return BlockCreationMonitor(
|
||||
this.vertx,
|
||||
@@ -81,7 +81,7 @@ class BlockCreationMonitorTest {
|
||||
startingBlockNumberExclusive = startingBlockNumberExclusive,
|
||||
blockCreationListener,
|
||||
lastProvenBlockNumberProvider,
|
||||
config
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -94,14 +94,14 @@ class BlockCreationMonitorTest {
|
||||
fakeL2RpcNode = TestingJsonRpcServer(
|
||||
vertx = vertx,
|
||||
recordRequestsResponses = true,
|
||||
responseObjectMapper = ethApiObjectMapper
|
||||
responseObjectMapper = ethApiObjectMapper,
|
||||
)
|
||||
blockCreationListener = BlockCreationListenerDouble()
|
||||
web3jClient = ExtendedWeb3JImpl(
|
||||
createWeb3jHttpClient(
|
||||
rpcUrl = "http://localhost:${fakeL2RpcNode.boundPort}",
|
||||
log = LogManager.getLogger("test.client.l2.web3j")
|
||||
)
|
||||
log = LogManager.getLogger("test.client.l2.web3j"),
|
||||
),
|
||||
)
|
||||
lastProvenBlockNumberProvider = LastProvenBlockNumberProviderDouble(99u)
|
||||
}
|
||||
@@ -116,7 +116,7 @@ class BlockCreationMonitorTest {
|
||||
startBlockNumber: ULong,
|
||||
numberOfBlocks: Int,
|
||||
startBlockHash: ByteArray = ByteArrayExt.random32(),
|
||||
startBlockParentHash: ByteArray = ByteArrayExt.random32()
|
||||
startBlockParentHash: ByteArray = ByteArrayExt.random32(),
|
||||
): List<Block> {
|
||||
var blockHash = startBlockHash
|
||||
var parentHash = startBlockParentHash
|
||||
@@ -124,7 +124,7 @@ class BlockCreationMonitorTest {
|
||||
createBlock(
|
||||
number = startBlockNumber + i.toULong(),
|
||||
hash = blockHash,
|
||||
parentHash = parentHash
|
||||
parentHash = parentHash,
|
||||
).also {
|
||||
blockHash = ByteArrayExt.random32()
|
||||
parentHash = it.hash
|
||||
@@ -147,7 +147,7 @@ class BlockCreationMonitorTest {
|
||||
fun `should stop fetching blocks after lastBlockNumberInclusiveToProcess`() {
|
||||
monitor = createBlockCreationMonitor(
|
||||
startingBlockNumberExclusive = 99,
|
||||
config = config.copy(lastL2BlockNumberToProcessInclusive = 103u)
|
||||
config = config.copy(lastL2BlockNumberToProcessInclusive = 103u),
|
||||
)
|
||||
|
||||
setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 20))
|
||||
@@ -170,7 +170,7 @@ class BlockCreationMonitorTest {
|
||||
fun `should notify lister only after block is considered final on L2`() {
|
||||
monitor = createBlockCreationMonitor(
|
||||
startingBlockNumberExclusive = 99,
|
||||
config = config.copy(blocksToFinalization = 2, blocksFetchLimit = 500)
|
||||
config = config.copy(blocksToFinalization = 2, blocksFetchLimit = 500),
|
||||
)
|
||||
|
||||
setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 200))
|
||||
@@ -217,7 +217,7 @@ class BlockCreationMonitorTest {
|
||||
monitor = createBlockCreationMonitor(
|
||||
startingBlockNumberExclusive = 99,
|
||||
blockCreationListener = fakeBuggyLister,
|
||||
config = config.copy(blocksToFinalization = 2, lastL2BlockNumberToProcessInclusive = 112u)
|
||||
config = config.copy(blocksToFinalization = 2, lastL2BlockNumberToProcessInclusive = 112u),
|
||||
)
|
||||
|
||||
setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 20))
|
||||
@@ -232,14 +232,14 @@ class BlockCreationMonitorTest {
|
||||
|
||||
// assert it got block only once and in order
|
||||
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
|
||||
fun `should be resilient to connection failures`() {
|
||||
monitor = createBlockCreationMonitor(
|
||||
startingBlockNumberExclusive = 99
|
||||
startingBlockNumberExclusive = 99,
|
||||
)
|
||||
|
||||
setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 200))
|
||||
@@ -268,7 +268,7 @@ class BlockCreationMonitorTest {
|
||||
@Test
|
||||
fun `should stop when reorg is detected above blocksToFinalization limit - manual intervention necessary`() {
|
||||
monitor = createBlockCreationMonitor(
|
||||
startingBlockNumberExclusive = 99
|
||||
startingBlockNumberExclusive = 99,
|
||||
)
|
||||
|
||||
// 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`() {
|
||||
monitor = createBlockCreationMonitor(
|
||||
startingBlockNumberExclusive = 99,
|
||||
config = config.copy(pollingInterval = 100.milliseconds)
|
||||
config = config.copy(pollingInterval = 100.milliseconds),
|
||||
)
|
||||
|
||||
val blocks = createBlocks(startBlockNumber = 99u, numberOfBlocks = 20)
|
||||
@@ -318,7 +318,7 @@ class BlockCreationMonitorTest {
|
||||
102UL,
|
||||
103UL,
|
||||
104UL,
|
||||
105UL
|
||||
105UL,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -326,7 +326,7 @@ class BlockCreationMonitorTest {
|
||||
@Test
|
||||
fun `start allow 2nd call when already started`() {
|
||||
monitor = createBlockCreationMonitor(
|
||||
startingBlockNumberExclusive = 99
|
||||
startingBlockNumberExclusive = 99,
|
||||
)
|
||||
setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 5))
|
||||
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`() {
|
||||
monitor = createBlockCreationMonitor(
|
||||
startingBlockNumberExclusive = 99,
|
||||
config = config.copy(blocksToFinalization = 0, blocksFetchLimit = 5)
|
||||
config = config.copy(blocksToFinalization = 0, blocksFetchLimit = 5),
|
||||
)
|
||||
|
||||
setupFakeExecutionLayerWithBlocks(createBlocks(startBlockNumber = 99u, numberOfBlocks = 30))
|
||||
|
||||
@@ -27,23 +27,23 @@ class ConsecutiveProvenBlobsProviderWithLastEndBlockNumberTrackerTest {
|
||||
endBlockNumber = 2UL,
|
||||
startBlockTimestamp = Instant.DISTANT_PAST,
|
||||
endBlockTimestamp = Instant.DISTANT_PAST,
|
||||
expectedShnarf = Random.nextBytes(32)
|
||||
expectedShnarf = Random.nextBytes(32),
|
||||
)
|
||||
val baseBlobAndBatchCounters = BlobAndBatchCounters(
|
||||
blobCounters = baseBlobCounters,
|
||||
executionProofs = BlockIntervals(1UL, listOf(2UL, 3UL))
|
||||
executionProofs = BlockIntervals(1UL, listOf(2UL, 3UL)),
|
||||
)
|
||||
val expectedEndBLockNumber = 10UL
|
||||
val lastBlobAndBatchCounters = baseBlobAndBatchCounters.copy(
|
||||
blobCounters = baseBlobCounters.copy(startBlockNumber = 3UL, endBlockNumber = expectedEndBLockNumber)
|
||||
blobCounters = baseBlobCounters.copy(startBlockNumber = 3UL, endBlockNumber = expectedEndBLockNumber),
|
||||
)
|
||||
whenever(repositoryMock.findConsecutiveProvenBlobs(any())).thenReturn(
|
||||
SafeFuture.completedFuture(
|
||||
listOf(
|
||||
baseBlobAndBatchCounters,
|
||||
lastBlobAndBatchCounters
|
||||
)
|
||||
)
|
||||
lastBlobAndBatchCounters,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
cache.findConsecutiveProvenBlobs(expectedEndBLockNumber.toLong())
|
||||
|
||||
@@ -22,12 +22,12 @@ class ForkChoiceUpdaterImplTest {
|
||||
fun dispatchFinalizedBlockNotification_allClientsSuccess() {
|
||||
val mockClient1 = mock<RollupForkChoiceUpdatedClient>()
|
||||
whenever(
|
||||
mockClient1.rollupForkChoiceUpdated(any())
|
||||
mockClient1.rollupForkChoiceUpdated(any()),
|
||||
)
|
||||
.thenReturn(SafeFuture.completedFuture(Ok(RollupForkChoiceUpdatedResponse("success"))))
|
||||
val mockClient2 = mock<RollupForkChoiceUpdatedClient>()
|
||||
whenever(
|
||||
mockClient2.rollupForkChoiceUpdated(any())
|
||||
mockClient2.rollupForkChoiceUpdated(any()),
|
||||
)
|
||||
.thenReturn(SafeFuture.completedFuture(Ok(RollupForkChoiceUpdatedResponse("success"))))
|
||||
|
||||
@@ -43,12 +43,12 @@ class ForkChoiceUpdaterImplTest {
|
||||
fun dispatchFinalizedBlockNotification_someClientsFail() {
|
||||
val mockClient1 = mock<RollupForkChoiceUpdatedClient>()
|
||||
whenever(
|
||||
mockClient1.rollupForkChoiceUpdated(any())
|
||||
mockClient1.rollupForkChoiceUpdated(any()),
|
||||
)
|
||||
.thenReturn(SafeFuture.completedFuture(Ok(RollupForkChoiceUpdatedResponse("success"))))
|
||||
val mockClient2 = mock<RollupForkChoiceUpdatedClient>()
|
||||
whenever(
|
||||
mockClient2.rollupForkChoiceUpdated(any())
|
||||
mockClient2.rollupForkChoiceUpdated(any()),
|
||||
)
|
||||
.thenReturn(SafeFuture.completedFuture(Err(ErrorResponse(RollupForkChoiceUpdatedError.UNKNOWN, ""))))
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class SimpleCompositeSafeFutureHandlerTest {
|
||||
handler2Calls.add("handler2:$value")
|
||||
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)
|
||||
@@ -34,8 +34,11 @@ class SimpleCompositeSafeFutureHandlerTest {
|
||||
val handler3Calls = mutableListOf<String>()
|
||||
val handlers = listOf(
|
||||
{ value: Long -> SafeFuture.completedFuture(handler1Calls.add("handler1:$value")) },
|
||||
{ value: Long -> handler2Calls.add("handler2:$value"); throw RuntimeException("Forced error") },
|
||||
{ value: Long -> SafeFuture.completedFuture(handler3Calls.add("handler3:$value")) }
|
||||
{ value: Long ->
|
||||
handler2Calls.add("handler2:$value")
|
||||
throw RuntimeException("Forced error")
|
||||
},
|
||||
{ value: Long -> SafeFuture.completedFuture(handler3Calls.add("handler3:$value")) },
|
||||
)
|
||||
|
||||
SimpleCompositeSafeFutureHandler(handlers).invoke(123)
|
||||
|
||||
@@ -5,7 +5,7 @@ import net.consensys.zkevm.coordinator.clients.ProverClient
|
||||
import tech.pegasys.teku.infrastructure.async.SafeFuture
|
||||
|
||||
class StartBlockNumberBasedSwitchPredicate<ProofRequest>(
|
||||
private val switchStartBlockNumberInclusive: ULong
|
||||
private val switchStartBlockNumberInclusive: ULong,
|
||||
) where ProofRequest : BlockInterval {
|
||||
fun invoke(proofRequest: ProofRequest): Boolean = proofRequest.startBlockNumber >= switchStartBlockNumberInclusive
|
||||
}
|
||||
@@ -13,7 +13,7 @@ class StartBlockNumberBasedSwitchPredicate<ProofRequest>(
|
||||
class ABProverClientRouter<ProofRequest, ProofResponse>(
|
||||
private val proverA: ProverClient<ProofRequest, ProofResponse>,
|
||||
private val proverB: ProverClient<ProofRequest, ProofResponse>,
|
||||
private val switchToProverBPredicate: (ProofRequest) -> Boolean
|
||||
private val switchToProverBPredicate: (ProofRequest) -> Boolean,
|
||||
) : ProverClient<ProofRequest, ProofResponse> {
|
||||
|
||||
override fun requestProof(proofRequest: ProofRequest): SafeFuture<ProofResponse> {
|
||||
|
||||
@@ -6,13 +6,13 @@ import kotlin.time.Duration
|
||||
data class ProversConfig(
|
||||
val proverA: ProverConfig,
|
||||
val switchBlockNumberInclusive: ULong?,
|
||||
val proverB: ProverConfig?
|
||||
val proverB: ProverConfig?,
|
||||
)
|
||||
|
||||
data class ProverConfig(
|
||||
val execution: FileBasedProverConfig,
|
||||
val blobCompression: FileBasedProverConfig,
|
||||
val proofAggregation: FileBasedProverConfig
|
||||
val proofAggregation: FileBasedProverConfig,
|
||||
)
|
||||
|
||||
data class FileBasedProverConfig(
|
||||
@@ -21,5 +21,5 @@ data class FileBasedProverConfig(
|
||||
val inprogressProvingSuffixPattern: String,
|
||||
val inprogressRequestWritingSuffix: String,
|
||||
val pollingInterval: Duration,
|
||||
val pollingTimeout: Duration
|
||||
val pollingTimeout: Duration,
|
||||
)
|
||||
|
||||
@@ -28,13 +28,13 @@ import tech.pegasys.teku.infrastructure.async.SafeFuture
|
||||
class FileBasedBlobCompressionProverClientV2(
|
||||
val config: FileBasedProverConfig,
|
||||
val vertx: Vertx,
|
||||
jsonObjectMapper: ObjectMapper = JsonSerialization.proofResponseMapperV1
|
||||
jsonObjectMapper: ObjectMapper = JsonSerialization.proofResponseMapperV1,
|
||||
) :
|
||||
GenericFileBasedProverClient<
|
||||
BlobCompressionProofRequest,
|
||||
BlobCompressionProof,
|
||||
BlobCompressionProofJsonRequest,
|
||||
BlobCompressionProofJsonResponse
|
||||
BlobCompressionProofJsonResponse,
|
||||
>(
|
||||
config = config,
|
||||
vertx = vertx,
|
||||
@@ -42,7 +42,7 @@ class FileBasedBlobCompressionProverClientV2(
|
||||
fileReader = FileReader(
|
||||
vertx,
|
||||
jsonObjectMapper,
|
||||
BlobCompressionProofJsonResponse::class.java
|
||||
BlobCompressionProofJsonResponse::class.java,
|
||||
),
|
||||
requestFileNameProvider = CompressionProofRequestFileNameProvider,
|
||||
responseFileNameProvider = CompressionProofResponseFileNameProvider,
|
||||
@@ -50,7 +50,7 @@ class FileBasedBlobCompressionProverClientV2(
|
||||
requestMapper = FileBasedBlobCompressionProverClientV2::requestDtoMapper,
|
||||
responseMapper = BlobCompressionProofJsonResponse::toDomainObject,
|
||||
proofTypeLabel = "blob",
|
||||
log = LogManager.getLogger(this::class.java)
|
||||
log = LogManager.getLogger(this::class.java),
|
||||
),
|
||||
BlobCompressionProverClientV2 {
|
||||
|
||||
@@ -59,7 +59,7 @@ class FileBasedBlobCompressionProverClientV2(
|
||||
return ProofIndex(
|
||||
startBlockNumber = request.startBlockNumber,
|
||||
endBlockNumber = request.endBlockNumber,
|
||||
hash = request.expectedShnarfResult.expectedShnarf
|
||||
hash = request.expectedShnarfResult.expectedShnarf,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ data class BatchExecutionProofRequestDto(
|
||||
val tracesEngineVersion: String,
|
||||
val type2StateManagerVersion: String?,
|
||||
val zkStateMerkleProof: ArrayNode,
|
||||
val blocksData: List<RlpBridgeLogsDto>
|
||||
val blocksData: List<RlpBridgeLogsDto>,
|
||||
)
|
||||
|
||||
data class RlpBridgeLogsDto(val rlp: String, val bridgeLogs: List<BridgeLogsDto>)
|
||||
@@ -40,7 +40,7 @@ data class BridgeLogsDto(
|
||||
val blockNumber: String,
|
||||
val address: String,
|
||||
val data: String,
|
||||
val topics: List<String>
|
||||
val topics: List<String>,
|
||||
) {
|
||||
companion object {
|
||||
fun fromDomainObject(ethLog: EthLog): BridgeLogsDto {
|
||||
@@ -53,14 +53,14 @@ data class BridgeLogsDto(
|
||||
blockNumber = ethLog.blockNumber.toHexString(),
|
||||
address = ethLog.address.encodeHex(),
|
||||
data = ethLog.data.encodeHex(),
|
||||
topics = ethLog.topics.map { it.encodeHex() }
|
||||
topics = ethLog.topics.map { it.encodeHex() },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class ExecutionProofRequestDtoMapper(
|
||||
private val encoder: BlockEncoder = BlockRLPEncoder
|
||||
private val encoder: BlockEncoder = BlockRLPEncoder,
|
||||
) : (BatchExecutionProofRequestV1) -> SafeFuture<BatchExecutionProofRequestDto> {
|
||||
override fun invoke(request: BatchExecutionProofRequestV1): SafeFuture<BatchExecutionProofRequestDto> {
|
||||
val blocksData = request.blocks.map { block ->
|
||||
@@ -79,8 +79,8 @@ internal class ExecutionProofRequestDtoMapper(
|
||||
tracesEngineVersion = request.tracesResponse.tracesEngineVersion,
|
||||
type2StateManagerVersion = request.type2StateData.zkStateManagerVersion,
|
||||
zkStateMerkleProof = request.type2StateData.zkStateMerkleProof,
|
||||
blocksData = blocksData
|
||||
)
|
||||
blocksData = blocksData,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -105,15 +105,15 @@ class FileBasedExecutionProverClientV2(
|
||||
executionProofRequestFileNameProvider: ProverFileNameProvider =
|
||||
ExecutionProofRequestFileNameProvider(
|
||||
tracesVersion = tracesVersion,
|
||||
stateManagerVersion = stateManagerVersion
|
||||
stateManagerVersion = stateManagerVersion,
|
||||
),
|
||||
executionProofResponseFileNameProvider: ProverFileNameProvider = ExecutionProofResponseFileNameProvider
|
||||
executionProofResponseFileNameProvider: ProverFileNameProvider = ExecutionProofResponseFileNameProvider,
|
||||
) :
|
||||
GenericFileBasedProverClient<
|
||||
BatchExecutionProofRequestV1,
|
||||
BatchExecutionProofResponse,
|
||||
BatchExecutionProofRequestDto,
|
||||
Any
|
||||
Any,
|
||||
>(
|
||||
config = config,
|
||||
vertx = vertx,
|
||||
@@ -125,19 +125,19 @@ class FileBasedExecutionProverClientV2(
|
||||
requestMapper = ExecutionProofRequestDtoMapper(),
|
||||
responseMapper = { throw UnsupportedOperationException("Batch execution proof response shall not be parsed!") },
|
||||
proofTypeLabel = "batch",
|
||||
log = LogManager.getLogger(FileBasedExecutionProverClientV2::class.java)
|
||||
log = LogManager.getLogger(FileBasedExecutionProverClientV2::class.java),
|
||||
),
|
||||
ExecutionProverClientV2 {
|
||||
|
||||
override fun parseResponse(
|
||||
responseFilePath: Path,
|
||||
proofIndex: ProofIndex
|
||||
proofIndex: ProofIndex,
|
||||
): SafeFuture<BatchExecutionProofResponse> {
|
||||
return SafeFuture.completedFuture(
|
||||
BatchExecutionProofResponse(
|
||||
startBlockNumber = proofIndex.startBlockNumber,
|
||||
endBlockNumber = proofIndex.endBlockNumber
|
||||
)
|
||||
endBlockNumber = proofIndex.endBlockNumber,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@ data class AggregationProofRequestDto(
|
||||
val compressionProofs: List<String>,
|
||||
val parentAggregationLastBlockTimestamp: Long,
|
||||
val parentAggregationLastL1RollingHashMessageNumber: Long,
|
||||
val parentAggregationLastL1RollingHash: String
|
||||
val parentAggregationLastL1RollingHash: String,
|
||||
) {
|
||||
companion object {
|
||||
fun fromDomainObject(
|
||||
proofsToAggregate: ProofsToAggregate,
|
||||
executionProofResponseFileNameProvider: ProverFileNameProvider,
|
||||
compressionProofResponseFileNameProvider: ProverFileNameProvider
|
||||
compressionProofResponseFileNameProvider: ProverFileNameProvider,
|
||||
): AggregationProofRequestDto {
|
||||
val executionProofsResponseFiles = proofsToAggregate.executionProofs
|
||||
.toIntervalList()
|
||||
@@ -35,8 +35,8 @@ data class AggregationProofRequestDto(
|
||||
executionProofResponseFileNameProvider.getFileName(
|
||||
ProofIndex(
|
||||
startBlockNumber = blockInterval.startBlockNumber,
|
||||
endBlockNumber = blockInterval.endBlockNumber
|
||||
)
|
||||
endBlockNumber = blockInterval.endBlockNumber,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -46,8 +46,8 @@ data class AggregationProofRequestDto(
|
||||
ProofIndex(
|
||||
startBlockNumber = it.startBlockNumber,
|
||||
endBlockNumber = it.endBlockNumber,
|
||||
hash = it.hash
|
||||
)
|
||||
hash = it.hash,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ data class AggregationProofRequestDto(
|
||||
parentAggregationLastBlockTimestamp = proofsToAggregate.parentAggregationLastBlockTimestamp.epochSeconds,
|
||||
parentAggregationLastL1RollingHashMessageNumber =
|
||||
proofsToAggregate.parentAggregationLastL1RollingHashMessageNumber.toLong(),
|
||||
parentAggregationLastL1RollingHash = proofsToAggregate.parentAggregationLastL1RollingHash.encodeHex()
|
||||
parentAggregationLastL1RollingHash = proofsToAggregate.parentAggregationLastL1RollingHash.encodeHex(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -65,15 +65,15 @@ data class AggregationProofRequestDto(
|
||||
|
||||
internal class AggregationRequestDtoMapper(
|
||||
private val executionProofResponseFileNameProvider: ProverFileNameProvider,
|
||||
private val compressionProofResponseFileNameProvider: ProverFileNameProvider
|
||||
private val compressionProofResponseFileNameProvider: ProverFileNameProvider,
|
||||
) : (ProofsToAggregate) -> SafeFuture<AggregationProofRequestDto> {
|
||||
override fun invoke(proofsToAggregate: ProofsToAggregate): SafeFuture<AggregationProofRequestDto> {
|
||||
return SafeFuture.completedFuture(
|
||||
AggregationProofRequestDto.fromDomainObject(
|
||||
proofsToAggregate,
|
||||
executionProofResponseFileNameProvider,
|
||||
compressionProofResponseFileNameProvider
|
||||
)
|
||||
compressionProofResponseFileNameProvider,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -95,13 +95,13 @@ class FileBasedProofAggregationClientV2(
|
||||
hashFunction: HashFunction = Sha256HashFunction(),
|
||||
executionProofResponseFileNameProvider: ProverFileNameProvider = ExecutionProofResponseFileNameProvider,
|
||||
compressionProofResponseFileNameProvider: ProverFileNameProvider = CompressionProofResponseFileNameProvider,
|
||||
jsonObjectMapper: ObjectMapper = JsonSerialization.proofResponseMapperV1
|
||||
jsonObjectMapper: ObjectMapper = JsonSerialization.proofResponseMapperV1,
|
||||
) :
|
||||
GenericFileBasedProverClient<
|
||||
ProofsToAggregate,
|
||||
ProofToFinalize,
|
||||
AggregationProofRequestDto,
|
||||
ProofToFinalizeJsonResponse
|
||||
ProofToFinalizeJsonResponse,
|
||||
>(
|
||||
config = config,
|
||||
vertx = vertx,
|
||||
@@ -109,18 +109,18 @@ class FileBasedProofAggregationClientV2(
|
||||
fileReader = FileReader(
|
||||
vertx,
|
||||
jsonObjectMapper,
|
||||
ProofToFinalizeJsonResponse::class.java
|
||||
ProofToFinalizeJsonResponse::class.java,
|
||||
),
|
||||
requestFileNameProvider = AggregationProofFileNameProvider,
|
||||
responseFileNameProvider = AggregationProofFileNameProvider,
|
||||
proofIndexProvider = createProofIndexProviderFn(hashFunction),
|
||||
requestMapper = AggregationRequestDtoMapper(
|
||||
executionProofResponseFileNameProvider = executionProofResponseFileNameProvider,
|
||||
compressionProofResponseFileNameProvider = compressionProofResponseFileNameProvider
|
||||
compressionProofResponseFileNameProvider = compressionProofResponseFileNameProvider,
|
||||
),
|
||||
responseMapper = ProofToFinalizeJsonResponse::toDomainObject,
|
||||
proofTypeLabel = "aggregation",
|
||||
log = LogManager.getLogger(this::class.java)
|
||||
log = LogManager.getLogger(this::class.java),
|
||||
),
|
||||
ProofAggregationProverClientV2 {
|
||||
|
||||
@@ -128,20 +128,20 @@ class FileBasedProofAggregationClientV2(
|
||||
fun createProofIndexProviderFn(
|
||||
hashFunction: HashFunction,
|
||||
executionProofResponseFileNameProvider: ProverFileNameProvider = ExecutionProofResponseFileNameProvider,
|
||||
compressionProofResponseFileNameProvider: ProverFileNameProvider = CompressionProofResponseFileNameProvider
|
||||
compressionProofResponseFileNameProvider: ProverFileNameProvider = CompressionProofResponseFileNameProvider,
|
||||
): (ProofsToAggregate) -> ProofIndex {
|
||||
return { request: ProofsToAggregate ->
|
||||
|
||||
val requestDto = AggregationProofRequestDto.fromDomainObject(
|
||||
proofsToAggregate = request,
|
||||
executionProofResponseFileNameProvider = executionProofResponseFileNameProvider,
|
||||
compressionProofResponseFileNameProvider = compressionProofResponseFileNameProvider
|
||||
compressionProofResponseFileNameProvider = compressionProofResponseFileNameProvider,
|
||||
)
|
||||
val hash = hashRequest(hashFunction, requestDto)
|
||||
ProofIndex(
|
||||
startBlockNumber = request.startBlockNumber,
|
||||
endBlockNumber = request.endBlockNumber,
|
||||
hash = hash
|
||||
hash = hash,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,13 +28,13 @@ open class GenericFileBasedProverClient<Request, Response, RequestDto, ResponseD
|
||||
private val responseFileNameProvider: ProverFileNameProvider,
|
||||
private val fileMonitor: FileMonitor = FileMonitor(
|
||||
vertx,
|
||||
FileMonitor.Config(config.pollingInterval, config.pollingTimeout)
|
||||
FileMonitor.Config(config.pollingInterval, config.pollingTimeout),
|
||||
),
|
||||
private val proofIndexProvider: (Request) -> ProofIndex = ::blockIntervalProofIndex,
|
||||
private val requestMapper: (Request) -> SafeFuture<RequestDto>,
|
||||
private val responseMapper: (ResponseDto) -> Response,
|
||||
private val proofTypeLabel: String,
|
||||
private val log: Logger = LogManager.getLogger(GenericFileBasedProverClient::class.java)
|
||||
private val log: Logger = LogManager.getLogger(GenericFileBasedProverClient::class.java),
|
||||
) : Supplier<Number>
|
||||
where Request : BlockInterval,
|
||||
Response : Any,
|
||||
@@ -62,7 +62,7 @@ open class GenericFileBasedProverClient<Request, Response, RequestDto, ResponseD
|
||||
"request already proven: {}={} reusedResponse={}",
|
||||
proofTypeLabel,
|
||||
proofIndex.intervalString(),
|
||||
responseFilePath
|
||||
responseFilePath,
|
||||
)
|
||||
SafeFuture.completedFuture(responseFilePath)
|
||||
} else {
|
||||
@@ -74,7 +74,7 @@ open class GenericFileBasedProverClient<Request, Response, RequestDto, ResponseD
|
||||
"request already in file system: {}={} reusedRequest={}",
|
||||
proofTypeLabel,
|
||||
proofIndex.intervalString(),
|
||||
requestFileFound
|
||||
requestFileFound,
|
||||
)
|
||||
SafeFuture.completedFuture(Unit)
|
||||
} else {
|
||||
@@ -83,7 +83,7 @@ open class GenericFileBasedProverClient<Request, Response, RequestDto, ResponseD
|
||||
fileWriter.write(
|
||||
proofRequestDto,
|
||||
requestFilePath,
|
||||
config.inprogressRequestWritingSuffix
|
||||
config.inprogressRequestWritingSuffix,
|
||||
).thenApply {
|
||||
Unit
|
||||
}
|
||||
@@ -104,13 +104,13 @@ open class GenericFileBasedProverClient<Request, Response, RequestDto, ResponseD
|
||||
proofTypeLabel,
|
||||
proofIndex.intervalString(),
|
||||
it.message,
|
||||
it
|
||||
it,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun waitForResponse(
|
||||
responseFilePath: Path
|
||||
responseFilePath: Path,
|
||||
): SafeFuture<Path> {
|
||||
return fileMonitor.monitor(responseFilePath).thenCompose {
|
||||
if (it is Err) {
|
||||
@@ -130,17 +130,17 @@ open class GenericFileBasedProverClient<Request, Response, RequestDto, ResponseD
|
||||
}
|
||||
|
||||
private fun findRequestFileIfAlreadyInFileSystem(
|
||||
requestFileName: String
|
||||
requestFileName: String,
|
||||
): SafeFuture<String?> {
|
||||
return fileMonitor.findFile(
|
||||
directory = config.requestsDirectory,
|
||||
pattern = inProgressFilePattern(requestFileName, config.inprogressProvingSuffixPattern)
|
||||
pattern = inProgressFilePattern(requestFileName, config.inprogressProvingSuffixPattern),
|
||||
)
|
||||
}
|
||||
|
||||
protected open fun parseResponse(
|
||||
responseFilePath: Path,
|
||||
proofIndex: ProofIndex
|
||||
proofIndex: ProofIndex,
|
||||
): SafeFuture<Response> {
|
||||
return fileReader.read(responseFilePath)
|
||||
.thenCompose { result ->
|
||||
@@ -152,7 +152,7 @@ open class GenericFileBasedProverClient<Request, Response, RequestDto, ResponseD
|
||||
log.error(
|
||||
"Failed to read response file={} errorMessage={}",
|
||||
responseFilePath,
|
||||
errorResponse.message
|
||||
errorResponse.message,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -165,13 +165,13 @@ open class GenericFileBasedProverClient<Request, Response, RequestDto, ResponseD
|
||||
fun <R : BlockInterval> blockIntervalProofIndex(request: R): ProofIndex {
|
||||
return ProofIndex(
|
||||
startBlockNumber = request.startBlockNumber,
|
||||
endBlockNumber = request.endBlockNumber
|
||||
endBlockNumber = request.endBlockNumber,
|
||||
)
|
||||
}
|
||||
|
||||
fun createDirectoryIfNotExists(
|
||||
directory: Path,
|
||||
log: Logger = LogManager.getLogger(GenericFileBasedProverClient::class.java)
|
||||
log: Logger = LogManager.getLogger(GenericFileBasedProverClient::class.java),
|
||||
) {
|
||||
try {
|
||||
if (directory.notExists()) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user