From 6e157404b6f7413c587562fe0531a71929122270 Mon Sep 17 00:00:00 2001
From: Pedro Novais <1478752+jpnovais@users.noreply.github.com>
Date: Mon, 13 Jan 2025 14:21:27 +0000
Subject: [PATCH 1/9] prover: Dockerfile remove legacy/unused data/work folder
(#537)
---
prover/Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/prover/Dockerfile b/prover/Dockerfile
index 678086c33..25f14ed67 100644
--- a/prover/Dockerfile
+++ b/prover/Dockerfile
@@ -30,7 +30,7 @@ RUN make bin/controller
FROM alpine:3
RUN apk add --no-cache bash musl-dev libgcc
-RUN mkdir -p /opt/linea/prover/lib/compressor /data/work /app/logs
+RUN mkdir -p /opt/linea/prover/lib/compressor /app/logs
# Import the LICENSE
COPY ./LICENSE /opt/linea/prover/
From 1ad613107969253deaee6fa0a940344ac62464cf Mon Sep 17 00:00:00 2001
From: Pedro Novais <1478752+jpnovais@users.noreply.github.com>
Date: Tue, 14 Jan 2025 16:39:02 +0000
Subject: [PATCH 2/9] coordinator: update traces limits-v2 (#548)
---
config/common/traces-limits-v2.toml | 23 ++++++++--------
...ator-docker-traces-v2-override.config.toml | 4 +--
.../coordinator-docker.config.toml | 9 +++----
config/coordinator/log4j2-dev.xml | 8 ++++++
.../app/config/CoordinatorConfigTest.kt | 27 ++++++++++---------
5 files changed, 39 insertions(+), 32 deletions(-)
diff --git a/config/common/traces-limits-v2.toml b/config/common/traces-limits-v2.toml
index 1f06f6de5..9e1d4285e 100644
--- a/config/common/traces-limits-v2.toml
+++ b/config/common/traces-limits-v2.toml
@@ -10,12 +10,12 @@ BLOCK_HASH = 512
EC_DATA = 262144
EUC = 65536
EXP = 8192
-EXT = 65536
+EXT = 1048576
GAS = 65536
HUB = 2097152
LOG_DATA = 65536
LOG_INFO = 4096
-MMIO = 2097152
+MMIO = 4194304
MMU = 4194304
MOD = 131072
MUL = 65536
@@ -23,21 +23,21 @@ MXP = 524288
OOB = 262144
RLP_ADDR = 4096
RLP_TXN = 131072
-RLP_TXN_RCPT = 32768
-ROM = 8388608
+RLP_TXN_RCPT = 65536
+ROM = 4194304
ROM_LEX = 1024
SHAKIRA_DATA = 32768
SHF = 65536
-STP = 32768
-TRM = 8192
+STP = 16384
+TRM = 32768
TXN_DATA = 8192
WCP = 262144
#
-# Reference table limits
+# Reference table limits, set to UInt.MAX_VALUE
#
-BIN_REFERENCE_TABLE = 196864
-SHF_REFERENCE_TABLE = 4096
-INSTRUCTION_DECODER = 512
+BIN_REFERENCE_TABLE = 4294967295
+SHF_REFERENCE_TABLE = 4294967295
+INSTRUCTION_DECODER = 4294967295
#
# Precompiles limits
#
@@ -48,7 +48,7 @@ PRECOMPILE_MODEXP_EFFECTIVE_CALLS = 4
PRECOMPILE_ECADD_EFFECTIVE_CALLS = 16384
PRECOMPILE_ECMUL_EFFECTIVE_CALLS = 32
PRECOMPILE_ECPAIRING_FINAL_EXPONENTIATIONS = 16
-PRECOMPILE_ECPAIRING_G2_MEMBERSHIP_CALLS = 64
+PRECOMPILE_ECPAIRING_G2_MEMBERSHIP_CALLS = 64
PRECOMPILE_ECPAIRING_MILLER_LOOPS = 64
PRECOMPILE_BLAKE_EFFECTIVE_CALLS = 600
PRECOMPILE_BLAKE_ROUNDS = 600
@@ -59,4 +59,3 @@ BLOCK_KECCAK = 8192
BLOCK_L1_SIZE = 1000000
BLOCK_L2_L1_LOGS = 16
BLOCK_TRANSACTIONS = 200
-
diff --git a/config/coordinator/coordinator-docker-traces-v2-override.config.toml b/config/coordinator/coordinator-docker-traces-v2-override.config.toml
index 096338011..c9e01f473 100644
--- a/config/coordinator/coordinator-docker-traces-v2-override.config.toml
+++ b/config/coordinator/coordinator-docker-traces-v2-override.config.toml
@@ -18,12 +18,12 @@ blob-compressor-version="V1_0_1"
expected-traces-api-version-v2="v0.8.0-rc8"
[traces.counters-v2]
endpoints=["http://traces-node-v2:8545/"]
-request-limit-per-endpoint=2
+request-limit-per-endpoint=1
request-retry.backoff-delay="PT1S"
request-retry.failures-warning-threshold=2
[traces.conflation-v2]
endpoints=["http://traces-node-v2:8545/"]
-request-limit-per-endpoint=2
+request-limit-per-endpoint=1
request-retry.backoff-delay="PT1S"
request-retry.failures-warning-threshold=2
diff --git a/config/coordinator/coordinator-docker.config.toml b/config/coordinator/coordinator-docker.config.toml
index 4778c8ebc..62ce6851f 100644
--- a/config/coordinator/coordinator-docker.config.toml
+++ b/config/coordinator/coordinator-docker.config.toml
@@ -126,12 +126,11 @@ fee-history-reward-percentile=15
last-hash-search-window=25
anchoring-receipt-polling-interval="PT01S"
max-receipt-retries=120
-# Number of children blocks to wait before considering a block "finalized"
-# and elegible for conflation and
+# Number of children blocks to wait before considering a won't be reverted and elegible for conflation.
# this a workaround to mitigate Geth fork issues with Clique PoA
# Coordinator will consider block as finalized after being included in the chain wtih children blocks-to-finalization
-# Recommended minimum of 2
-blocks-to-finalization=2
+# Recommended: Geth sequencer minimum of 2, Besu sequencer minimum of 1, 0 is safe localy
+blocks-to-finalization=0
[blob-submission]
disabled=true
@@ -153,7 +152,7 @@ proof-submission-delay="PT1S"
[proof-aggregation]
aggregation-proofs-limit=3
-aggregation-deadline="PT1M"
+aggregation-deadline="PT10S"
aggregation-coordinator-polling-interval="PT2S"
deadline-check-interval="PT8S"
target-end-blocks=[]
diff --git a/config/coordinator/log4j2-dev.xml b/config/coordinator/log4j2-dev.xml
index 48aa11611..dbd489ee6 100644
--- a/config/coordinator/log4j2-dev.xml
+++ b/config/coordinator/log4j2-dev.xml
@@ -100,6 +100,10 @@
+
+
+
+
@@ -112,6 +116,10 @@
+
+
+
+
diff --git a/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/CoordinatorConfigTest.kt b/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/CoordinatorConfigTest.kt
index 9e1dfdec7..33005abe6 100644
--- a/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/CoordinatorConfigTest.kt
+++ b/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/CoordinatorConfigTest.kt
@@ -100,12 +100,12 @@ class CoordinatorConfigTest {
TracingModuleV2.EC_DATA to 262144u,
TracingModuleV2.EUC to 65536u,
TracingModuleV2.EXP to 8192u,
- TracingModuleV2.EXT to 65536u,
+ TracingModuleV2.EXT to 1048576u,
TracingModuleV2.GAS to 65536u,
TracingModuleV2.HUB to 2097152u,
TracingModuleV2.LOG_DATA to 65536u,
TracingModuleV2.LOG_INFO to 4096u,
- TracingModuleV2.MMIO to 2097152u,
+ TracingModuleV2.MMIO to 4194304u,
TracingModuleV2.MMU to 4194304u,
TracingModuleV2.MOD to 131072u,
TracingModuleV2.MUL to 65536u,
@@ -113,18 +113,18 @@ class CoordinatorConfigTest {
TracingModuleV2.OOB to 262144u,
TracingModuleV2.RLP_ADDR to 4096u,
TracingModuleV2.RLP_TXN to 131072u,
- TracingModuleV2.RLP_TXN_RCPT to 32768u,
- TracingModuleV2.ROM to 8388608u,
+ TracingModuleV2.RLP_TXN_RCPT to 65536u,
+ TracingModuleV2.ROM to 4194304u,
TracingModuleV2.ROM_LEX to 1024u,
TracingModuleV2.SHAKIRA_DATA to 32768u,
TracingModuleV2.SHF to 65536u,
- TracingModuleV2.STP to 32768u,
- TracingModuleV2.TRM to 8192u,
+ TracingModuleV2.STP to 16384u,
+ TracingModuleV2.TRM to 32768u,
TracingModuleV2.TXN_DATA to 8192u,
TracingModuleV2.WCP to 262144u,
- TracingModuleV2.BIN_REFERENCE_TABLE to 196864u,
- TracingModuleV2.SHF_REFERENCE_TABLE to 4096u,
- TracingModuleV2.INSTRUCTION_DECODER to 512u,
+ TracingModuleV2.BIN_REFERENCE_TABLE to 4294967295u,
+ TracingModuleV2.SHF_REFERENCE_TABLE to 4294967295u,
+ TracingModuleV2.INSTRUCTION_DECODER to 4294967295u,
TracingModuleV2.PRECOMPILE_ECRECOVER_EFFECTIVE_CALLS to 128u,
TracingModuleV2.PRECOMPILE_SHA2_BLOCKS to 671u,
TracingModuleV2.PRECOMPILE_RIPEMD_BLOCKS to 671u,
@@ -235,7 +235,7 @@ class CoordinatorConfigTest {
private val aggregationConfig = AggregationConfig(
aggregationProofsLimit = 3,
- aggregationDeadline = Duration.parse("PT1M"),
+ aggregationDeadline = Duration.parse("PT10S"),
aggregationCoordinatorPollingInterval = Duration.parse("PT2S"),
deadlineCheckInterval = Duration.parse("PT8S")
)
@@ -359,7 +359,7 @@ class CoordinatorConfigTest {
maxFeePerGasCap = 100000000000u,
feeHistoryBlockCount = 4U,
feeHistoryRewardPercentile = 15.0,
- blocksToFinalization = 2U,
+ blocksToFinalization = 0U,
lastHashSearchWindow = 25U,
anchoringReceiptPollingInterval = Duration.parse("PT01S"),
maxReceiptRetries = 120U
@@ -837,13 +837,14 @@ class CoordinatorConfigTest {
blobCompressorVersion = BlobCompressorVersion.V1_0_1,
expectedTracesApiVersionV2 = "v0.8.0-rc8",
conflationV2 = tracesConfig.conflation.copy(
- endpoints = listOf(URI("http://traces-node-v2:8545/").toURL())
+ endpoints = listOf(URI("http://traces-node-v2:8545/").toURL()),
+ requestLimitPerEndpoint = 1U
),
countersV2 = TracesConfig.FunctionalityEndpoint(
listOf(
URI("http://traces-node-v2:8545/").toURL()
),
- requestLimitPerEndpoint = 2U,
+ requestLimitPerEndpoint = 1U,
requestRetry = RequestRetryConfigTomlFriendly(
backoffDelay = Duration.parse("PT1S"),
failuresWarningThreshold = 2
From 27cc9eb0900999246c8d9a7c27352bc2c59b2907 Mon Sep 17 00:00:00 2001
From: Pedro Novais <1478752+jpnovais@users.noreply.github.com>
Date: Wed, 15 Jan 2025 08:37:48 +0000
Subject: [PATCH 3/9] Coordinator fix logging (#551)
* coordinator: log retried errors as info/debug instead of error
---
.../ProofGeneratingConflationHandlerImpl.kt | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/coordinator/core/src/main/kotlin/net/consensys/zkevm/ethereum/coordination/conflation/ProofGeneratingConflationHandlerImpl.kt b/coordinator/core/src/main/kotlin/net/consensys/zkevm/ethereum/coordination/conflation/ProofGeneratingConflationHandlerImpl.kt
index 0a258556d..9da2cac96 100644
--- a/coordinator/core/src/main/kotlin/net/consensys/zkevm/ethereum/coordination/conflation/ProofGeneratingConflationHandlerImpl.kt
+++ b/coordinator/core/src/main/kotlin/net/consensys/zkevm/ethereum/coordination/conflation/ProofGeneratingConflationHandlerImpl.kt
@@ -38,7 +38,12 @@ class ProofGeneratingConflationHandlerImpl(
vertx = vertx,
backoffDelay = config.conflationAndProofGenerationRetryInterval,
exceptionConsumer = {
- log.error("Conflation and proof creation flow failed!", it)
+ // log failure as warning, but keeps on retrying...
+ log.warn(
+ "conflation and proof creation flow failed batch={} errorMessage={}",
+ blockIntervalString,
+ it.message
+ )
}
) {
conflationToProofCreation(conflation)
@@ -46,7 +51,7 @@ class ProofGeneratingConflationHandlerImpl(
}.getOrElse { error -> SafeFuture.failedFuture(error) }
.whenException { th ->
log.error(
- "Traces conflation or proof failed: batch={} errorMessage={}",
+ "traces conflation or proof request failed: batch={} errorMessage={}",
blockIntervalString,
th.message,
th
@@ -60,8 +65,8 @@ class ProofGeneratingConflationHandlerImpl(
return tracesProductionCoordinator
.conflateExecutionTraces(blockNumbersAndHash)
.whenException { th ->
- log.error(
- "Traces conflation failed: batch={} errorMessage={}",
+ log.debug(
+ "traces conflation failed: batch={} errorMessage={}",
conflation.conflationResult.intervalString(),
th.message,
th
@@ -79,7 +84,7 @@ class ProofGeneratingConflationHandlerImpl(
log.info("execution proof generated: batch={}", blockIntervalString)
}
.whenException { th ->
- log.error(
+ log.debug(
"execution proof failure: batch={} errorMessage={}",
blockIntervalString,
th.message,
From 522d9f18ef2dc6a0d133affb6cd13a5d2805c42e Mon Sep 17 00:00:00 2001
From: AlexandreBelling
Date: Wed, 15 Jan 2025 09:48:45 +0100
Subject: [PATCH 4/9] chores(ci): deactivate the slack notification for
prover-ci (#546)
* chores(ci): deactivate the slack notification for prover-ci
* Update .github/workflows/prover-testing.yml
---------
Signed-off-by: AlexandreBelling
Co-authored-by: kyzooghost <73516204+kyzooghost@users.noreply.github.com>
---
.github/workflows/prover-testing.yml | 56 +---------------------------
1 file changed, 1 insertion(+), 55 deletions(-)
diff --git a/.github/workflows/prover-testing.yml b/.github/workflows/prover-testing.yml
index 29780c57e..692c9493b 100644
--- a/.github/workflows/prover-testing.yml
+++ b/.github/workflows/prover-testing.yml
@@ -1,13 +1,6 @@
name: Prover testing CI
-on:
- workflow_call:
- secrets:
- SLACK_WEBHOOK_CI_PROVER_FAIL:
- required: true
- SLACK_WEBHOOK_CI_PROVER_SUCCESS:
- required: true
-
+on: workflow_call
env:
GOPROXY: "https://proxy.golang.org"
@@ -93,50 +86,3 @@ jobs:
if: matrix.go-version == '1.20.x'
run: |
go test -p=1 -tags=nocorset,fuzzlight -timeout=30m -short -race ./...
-
- slack-workflow-status-failed:
- if: failure()
- name: Prover notify slack
- needs:
- - staticcheck
- - test
- runs-on: [self-hosted, ubuntu-20.04, X64, small]
- steps:
- - name: Notify slack -- workflow failed
- id: slack
- uses: slackapi/slack-github-action@v1.23.0
- with:
- payload: |
- {
- "actor": "${{ github.actor }}",
- "repo": "${{ github.repository }}",
- "status": "FAIL",
- "title": "${{ github.event.pull_request.title }}",
- "pr": "${{ github.event.pull_request.head.ref }}"
- }
- env:
- SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_CI_PROVER_FAIL }}
-
- slack-workflow-status-success:
- if: success()
- name: Prover notify slack
- needs:
- - staticcheck
- - test
- runs-on: [self-hosted, ubuntu-20.04, X64, small]
- steps:
- - name: Notify slack -- workflow succeeded
- id: slack
- uses: slackapi/slack-github-action@v1.23.0
- with:
- payload: |
- {
- "actor": "${{ github.actor }}",
- "repo": "${{ github.repository }}",
- "status": "SUCCESS",
- "title": "${{ github.event.pull_request.title }}",
- "pr": "${{ github.event.pull_request.head.ref }}"
- }
- env:
- SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_CI_PROVER_SUCCESS }}
-
From 4cb0c60fe0c1a69480a58faef7463b5d85535ba7 Mon Sep 17 00:00:00 2001
From: Pedro Novais <1478752+jpnovais@users.noreply.github.com>
Date: Wed, 15 Jan 2025 10:18:04 +0000
Subject: [PATCH 5/9] coordinator: decouple configs test from real configs
(#552)
* coordinator: decouple configs test from real configs
---
.../linea/coordinator/config/ConfigLoader.kt | 136 ++++
.../coordinator/app/CoordinatorAppCli.kt | 147 +----
.../app/config/CoordinatorConfigTest.kt | 606 ++++--------------
.../app/config/ExpectedGasPriceMultipliers.kt | 172 +++++
.../app/config/ExpectedTracesLimitsV1.kt | 48 ++
.../app/config/ExpectedTracesLimitsV2.kt | 60 ++
...coordinator-traces-v2-override.config.toml | 40 ++
...oordinator-web3signer-override.config.toml | 13 +
.../resources/configs/coordinator.config.toml | 292 +++++++++
...gas-price-cap-time-of-day-multipliers.toml | 184 ++++++
.../configs/smart-contract-errors.toml | 10 +
.../resources/configs/traces-limits-v1.toml | 40 ++
.../resources/configs/traces-limits-v2.toml | 53 ++
13 files changed, 1175 insertions(+), 626 deletions(-)
create mode 100644 coordinator/app/src/main/kotlin/linea/coordinator/config/ConfigLoader.kt
create mode 100644 coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/ExpectedGasPriceMultipliers.kt
create mode 100644 coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/ExpectedTracesLimitsV1.kt
create mode 100644 coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/ExpectedTracesLimitsV2.kt
create mode 100644 coordinator/app/src/test/resources/configs/coordinator-traces-v2-override.config.toml
create mode 100644 coordinator/app/src/test/resources/configs/coordinator-web3signer-override.config.toml
create mode 100644 coordinator/app/src/test/resources/configs/coordinator.config.toml
create mode 100644 coordinator/app/src/test/resources/configs/gas-price-cap-time-of-day-multipliers.toml
create mode 100644 coordinator/app/src/test/resources/configs/smart-contract-errors.toml
create mode 100644 coordinator/app/src/test/resources/configs/traces-limits-v1.toml
create mode 100644 coordinator/app/src/test/resources/configs/traces-limits-v2.toml
diff --git a/coordinator/app/src/main/kotlin/linea/coordinator/config/ConfigLoader.kt b/coordinator/app/src/main/kotlin/linea/coordinator/config/ConfigLoader.kt
new file mode 100644
index 000000000..d80c1c1d5
--- /dev/null
+++ b/coordinator/app/src/main/kotlin/linea/coordinator/config/ConfigLoader.kt
@@ -0,0 +1,136 @@
+package linea.coordinator.config
+
+import com.github.michaelbull.result.Err
+import com.github.michaelbull.result.Ok
+import com.github.michaelbull.result.Result
+import com.github.michaelbull.result.get
+import com.github.michaelbull.result.getOrElse
+import com.sksamuel.hoplite.ConfigLoaderBuilder
+import com.sksamuel.hoplite.addPathSource
+import net.consensys.linea.traces.TracesCountersV1
+import net.consensys.linea.traces.TracesCountersV2
+import net.consensys.zkevm.coordinator.app.config.CoordinatorConfig
+import net.consensys.zkevm.coordinator.app.config.CoordinatorConfigTomlDto
+import net.consensys.zkevm.coordinator.app.config.GasPriceCapTimeOfDayMultipliersConfig
+import net.consensys.zkevm.coordinator.app.config.SmartContractErrorCodesConfig
+import net.consensys.zkevm.coordinator.app.config.TracesLimitsV1ConfigFile
+import net.consensys.zkevm.coordinator.app.config.TracesLimitsV2ConfigFile
+import org.apache.logging.log4j.LogManager
+import org.apache.logging.log4j.Logger
+import java.nio.file.Path
+
+inline fun loadConfigsOrError(
+ configFiles: List
+): Result {
+ val confBuilder: ConfigLoaderBuilder = ConfigLoaderBuilder.Companion.empty().addDefaults()
+ for (configFile in configFiles.reversed()) {
+ // files must be added in reverse order for overriding
+ confBuilder.addPathSource(configFile, false)
+ }
+
+ return confBuilder.build().loadConfig(emptyList()).let { config ->
+ if (config.isInvalid()) {
+ Err(config.getInvalidUnsafe().description())
+ } else {
+ Ok(config.getUnsafe())
+ }
+ }
+}
+
+fun logErrorIfPresent(
+ configName: String,
+ configFiles: List,
+ configLoadingResult: Result,
+ logger: Logger
+) {
+ if (configLoadingResult is Err) {
+ logger.error("Failed to load $configName from files=$configFiles with error=${configLoadingResult.error}")
+ }
+}
+
+inline fun loadConfigsAndLogErrors(
+ configFiles: List,
+ configName: String,
+ logger: Logger = LogManager.getLogger("linea.coordinator.config")
+): Result {
+ return loadConfigsOrError(configFiles)
+ .also { logErrorIfPresent(configName, configFiles, it, logger) }
+}
+
+fun loadConfigsOrError(
+ coordinatorConfigFiles: List,
+ tracesLimitsFileV1: Path?,
+ tracesLimitsFileV2: Path?,
+ gasPriceCapTimeOfDayMultipliersFile: Path,
+ smartContractErrorsFile: Path,
+ logger: Logger = LogManager.getLogger("linea.coordinator.config")
+): Result {
+ val coordinatorBaseConfigs =
+ loadConfigsAndLogErrors(coordinatorConfigFiles, "coordinator", logger)
+ val tracesLimitsV1Configs = tracesLimitsFileV1
+ ?.let { loadConfigsAndLogErrors(listOf(it), "traces limit v1", logger) }
+ val tracesLimitsV2Configs = tracesLimitsFileV2
+ ?.let { loadConfigsAndLogErrors(listOf(it), "traces limits v2", logger) }
+ val gasPriceCapTimeOfDayMultipliersConfig =
+ loadConfigsAndLogErrors(
+ listOf(gasPriceCapTimeOfDayMultipliersFile),
+ "l1 submission gas prices caps",
+ logger
+ )
+ val smartContractErrorsConfig = loadConfigsAndLogErrors(
+ listOf(smartContractErrorsFile),
+ "smart contract errors",
+ logger
+ )
+ val configError = listOf(
+ coordinatorBaseConfigs,
+ tracesLimitsV1Configs,
+ tracesLimitsV1Configs,
+ gasPriceCapTimeOfDayMultipliersConfig,
+ smartContractErrorsConfig
+ )
+ .find { it is Err }
+
+ if (configError != null) {
+ @Suppress("UNCHECKED_CAST")
+ return configError as Result
+ }
+
+ val baseConfig = coordinatorBaseConfigs.get()!!
+ val finalConfig = baseConfig.copy(
+ conflation = baseConfig.conflation.copy(
+ _tracesLimitsV1 = tracesLimitsV1Configs?.get()?.tracesLimits?.let { TracesCountersV1(it) },
+ _tracesLimitsV2 = tracesLimitsV2Configs?.get()?.tracesLimits?.let { TracesCountersV2(it) },
+ _smartContractErrors = smartContractErrorsConfig.get()!!.smartContractErrors
+ ),
+ l1DynamicGasPriceCapService = baseConfig.l1DynamicGasPriceCapService.copy(
+ gasPriceCapCalculation = baseConfig.l1DynamicGasPriceCapService.gasPriceCapCalculation.copy(
+ timeOfDayMultipliers = gasPriceCapTimeOfDayMultipliersConfig.get()?.gasPriceCapTimeOfDayMultipliers
+ )
+ )
+ )
+ return Ok(finalConfig)
+}
+
+fun loadConfigs(
+ coordinatorConfigFiles: List,
+ tracesLimitsFileV1: Path?,
+ tracesLimitsFileV2: Path?,
+ gasPriceCapTimeOfDayMultipliersFile: Path,
+ smartContractErrorsFile: Path,
+ logger: Logger = LogManager.getLogger("linea.coordinator.config")
+): CoordinatorConfig {
+ loadConfigsOrError(
+ coordinatorConfigFiles,
+ tracesLimitsFileV1,
+ tracesLimitsFileV2,
+ gasPriceCapTimeOfDayMultipliersFile,
+ smartContractErrorsFile,
+ logger
+ ).let {
+ return it
+ .getOrElse {
+ throw RuntimeException("Invalid configurations: $it")
+ }.reified()
+ }
+}
diff --git a/coordinator/app/src/main/kotlin/net/consensys/zkevm/coordinator/app/CoordinatorAppCli.kt b/coordinator/app/src/main/kotlin/net/consensys/zkevm/coordinator/app/CoordinatorAppCli.kt
index e552add8c..febd8afec 100644
--- a/coordinator/app/src/main/kotlin/net/consensys/zkevm/coordinator/app/CoordinatorAppCli.kt
+++ b/coordinator/app/src/main/kotlin/net/consensys/zkevm/coordinator/app/CoordinatorAppCli.kt
@@ -1,21 +1,6 @@
package net.consensys.zkevm.coordinator.app
-import com.github.michaelbull.result.Err
-import com.github.michaelbull.result.Ok
-import com.github.michaelbull.result.Result
-import com.github.michaelbull.result.get
-import com.github.michaelbull.result.getError
-import com.github.michaelbull.result.onFailure
-import com.sksamuel.hoplite.ConfigLoaderBuilder
-import com.sksamuel.hoplite.addFileSource
-import net.consensys.linea.traces.TracesCountersV1
-import net.consensys.linea.traces.TracesCountersV2
import net.consensys.zkevm.coordinator.app.config.CoordinatorConfig
-import net.consensys.zkevm.coordinator.app.config.CoordinatorConfigTomlDto
-import net.consensys.zkevm.coordinator.app.config.GasPriceCapTimeOfDayMultipliersConfig
-import net.consensys.zkevm.coordinator.app.config.SmartContractErrorCodesConfig
-import net.consensys.zkevm.coordinator.app.config.TracesLimitsV1ConfigFile
-import net.consensys.zkevm.coordinator.app.config.TracesLimitsV2ConfigFile
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
import picocli.CommandLine
@@ -115,13 +100,14 @@ internal constructor(private val errorWriter: PrintWriter, private val startActi
}
}
- val configs = validateConfigs(
- tracesLimitsFile,
- tracesLimitsV2File,
- smartContractErrorsFile,
- gasPriceCapTimeOfDayMultipliersFile,
- configFiles
- ) ?: return 1
+ val configs = linea.coordinator.config.loadConfigs(
+ coordinatorConfigFiles = configFiles.map { it.toPath() },
+ tracesLimitsFileV1 = tracesLimitsFile?.toPath(),
+ tracesLimitsFileV2 = tracesLimitsV2File?.toPath(),
+ smartContractErrorsFile = smartContractErrorsFile.toPath(),
+ gasPriceCapTimeOfDayMultipliersFile = gasPriceCapTimeOfDayMultipliersFile.toPath(),
+ logger = logger
+ )
if (checkConfigsOnly) {
logger.info("All configs are valid. Final configs: {}", configs)
@@ -144,7 +130,7 @@ internal constructor(private val errorWriter: PrintWriter, private val startActi
}
fun reportUserError(ex: Throwable) {
- logger.fatal(ex.message, ex)
+ logger.fatal(ex.message)
errorWriter.println(ex.message)
printUsage(errorWriter)
}
@@ -155,97 +141,6 @@ internal constructor(private val errorWriter: PrintWriter, private val startActi
outputWriter.println(COMMAND_NAME + " --help")
}
- private fun validateConfigs(
- tracesLimitsFile: File?,
- tracesLimitsV2File: File?,
- smartContractErrorsFile: File,
- gasPriceCapTimeOfDayMultipliersFile: File,
- coordinatorConfigFiles: List
- ): CoordinatorConfig? {
- var hasConfigError = false
- val tracesLimitsV1Configs = if (tracesLimitsFile == null) {
- null
- } else {
- loadConfigsOrError(listOf(tracesLimitsFile))
- }
-
- val tracesLimitsV2Configs = if (tracesLimitsV2File == null) {
- null
- } else {
- loadConfigsOrError(listOf(tracesLimitsV2File))
- }
-
- val smartContractErrorCodes =
- loadConfigsOrError(listOf(smartContractErrorsFile))
-
- val gasPriceCapTimeOfDayMultipliers =
- loadConfigsOrError(listOf(gasPriceCapTimeOfDayMultipliersFile))
-
- val configs = loadConfigsOrError(coordinatorConfigFiles)
-
- if (tracesLimitsV1Configs is Err) {
- hasConfigError = true
- logger.error("Reading {} failed: {}", tracesLimitsFile, tracesLimitsV1Configs.getError())
- } else if (tracesLimitsV1Configs is Ok) {
- runCatching {
- TracesCountersV1(tracesLimitsV1Configs.get()!!.tracesLimits)
- }.getOrElse {
- hasConfigError = true
- logger.error("Traces limits file {} is incomplete. {}", tracesLimitsFile, it.message)
- }
- }
-
- if (tracesLimitsV2Configs is Err) {
- hasConfigError = true
- logger.error("Reading {} failed: {}", tracesLimitsV2File, tracesLimitsV2Configs.getError())
- } else if (tracesLimitsV2Configs is Ok) {
- runCatching {
- TracesCountersV2(tracesLimitsV2Configs.get()!!.tracesLimits)
- }.getOrElse {
- hasConfigError = true
- logger.error("Traces limits file {} is incomplete. {}", tracesLimitsV2File, it.message)
- }
- }
-
- if (smartContractErrorCodes is Err) {
- hasConfigError = true
- logger.error("Reading {} failed: {}", smartContractErrorsFile, smartContractErrorCodes.getError())
- }
-
- if (gasPriceCapTimeOfDayMultipliers is Err) {
- hasConfigError = true
- logger.error(
- "Reading {} failed: {}",
- gasPriceCapTimeOfDayMultipliersFile,
- gasPriceCapTimeOfDayMultipliers.getError()
- )
- }
-
- if (configs is Err) {
- hasConfigError = true
- logger.error("Reading {} failed: {}", configFiles, configs.getError())
- }
-
- return if (hasConfigError) {
- null
- } else {
- configs.get()?.let { config: CoordinatorConfigTomlDto ->
- config.copy(
- conflation = config.conflation.copy(
- _tracesLimitsV1 = tracesLimitsV1Configs?.get()?.tracesLimits?.let { TracesCountersV1(it) },
- _tracesLimitsV2 = tracesLimitsV2Configs?.get()?.tracesLimits?.let { TracesCountersV2(it) },
- _smartContractErrors = smartContractErrorCodes.get()?.smartContractErrors
- ),
- l1DynamicGasPriceCapService = config.l1DynamicGasPriceCapService.copy(
- gasPriceCapCalculation = config.l1DynamicGasPriceCapService.gasPriceCapCalculation.copy(
- timeOfDayMultipliers = gasPriceCapTimeOfDayMultipliers.get()?.gasPriceCapTimeOfDayMultipliers
- )
- )
- ).reified()
- }
- }
- }
-
/**
* Not using a static field for this log instance because some code in this class executes prior
* to the logging configuration being applied so it's not always safe to use the logger.
@@ -267,29 +162,5 @@ internal constructor(private val errorWriter: PrintWriter, private val startActi
val errorWriter = PrintWriter(System.err, true, Charset.defaultCharset())
return CoordinatorAppCli(errorWriter, startAction)
}
-
- inline fun loadConfigs(configFiles: List, errorWriter: PrintWriter): T? {
- return loadConfigsOrError(configFiles).onFailure { error ->
- errorWriter.println(error)
- }.get()
- }
-
- inline fun loadConfigsOrError(
- configFiles: List
- ): Result {
- val confBuilder: ConfigLoaderBuilder = ConfigLoaderBuilder.Companion.empty().addDefaults()
- for (configFile in configFiles.reversed()) {
- // files must be added in reverse order for overriding
- confBuilder.addFileSource(configFile, false)
- }
-
- return confBuilder.build().loadConfig(emptyList()).let { config ->
- if (config.isInvalid()) {
- Err(config.getInvalidUnsafe().description())
- } else {
- Ok(config.getUnsafe())
- }
- }
- }
}
}
diff --git a/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/CoordinatorConfigTest.kt b/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/CoordinatorConfigTest.kt
index 33005abe6..3b62a295a 100644
--- a/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/CoordinatorConfigTest.kt
+++ b/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/CoordinatorConfigTest.kt
@@ -1,10 +1,9 @@
package net.consensys.zkevm.coordinator.app.config
-import com.github.michaelbull.result.get
import com.github.michaelbull.result.getError
-import com.github.michaelbull.result.onFailure
-import com.github.michaelbull.result.onSuccess
import com.sksamuel.hoplite.Masked
+import linea.coordinator.config.loadConfigs
+import linea.coordinator.config.loadConfigsOrError
import net.consensys.linea.BlockParameter
import net.consensys.linea.blob.BlobCompressorVersion
import net.consensys.linea.ethereum.gaspricing.BoundableFeeCalculator
@@ -15,178 +14,39 @@ import net.consensys.linea.ethereum.gaspricing.staticcap.MinerExtraDataV1Calcula
import net.consensys.linea.ethereum.gaspricing.staticcap.TransactionCostCalculator
import net.consensys.linea.ethereum.gaspricing.staticcap.VariableFeesCalculator
import net.consensys.linea.jsonrpc.client.RequestRetryConfig
-import net.consensys.linea.traces.TracesCountersV1
-import net.consensys.linea.traces.TracesCountersV2
-import net.consensys.linea.traces.TracingModuleV1
-import net.consensys.linea.traces.TracingModuleV2
-import net.consensys.linea.web3j.SmartContractErrors
-import net.consensys.zkevm.coordinator.app.CoordinatorAppCli
import net.consensys.zkevm.coordinator.app.L2NetworkGasPricingService
import net.consensys.zkevm.coordinator.clients.prover.FileBasedProverConfig
import net.consensys.zkevm.coordinator.clients.prover.ProverConfig
import net.consensys.zkevm.coordinator.clients.prover.ProversConfig
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Assertions.fail
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertDoesNotThrow
import org.junit.jupiter.api.assertThrows
-import java.io.File
import java.math.BigInteger
import java.net.URI
import java.nio.file.Path
+import java.nio.file.Paths
import java.time.Duration
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds
class CoordinatorConfigTest {
companion object {
-
private val apiConfig = ApiConfig(9545U)
-
private val conflationConfig = ConflationConfig(
consistentNumberOfBlocksOnL1ToWait = 1,
conflationDeadline = Duration.parse("PT6S"),
conflationDeadlineCheckInterval = Duration.parse("PT3S"),
conflationDeadlineLastBlockConfirmationDelay = Duration.parse("PT2S"),
blocksLimit = 2,
- _tracesLimitsV1 = TracesCountersV1(
- mapOf(
- TracingModuleV1.ADD to 524288U,
- TracingModuleV1.BIN to 262144U,
- TracingModuleV1.BIN_RT to 262144U,
- TracingModuleV1.EC_DATA to 4096U,
- TracingModuleV1.EXT to 131072U,
- TracingModuleV1.HUB to 2097152U,
- TracingModuleV1.INSTRUCTION_DECODER to 512U,
- TracingModuleV1.MMIO to 131072U,
- TracingModuleV1.MMU to 131072U,
- TracingModuleV1.MMU_ID to 131072U,
- TracingModuleV1.MOD to 131072U,
- TracingModuleV1.MUL to 65536U,
- TracingModuleV1.MXP to 524288U,
- TracingModuleV1.PHONEY_RLP to 32768U,
- TracingModuleV1.PUB_HASH to 32768U,
- TracingModuleV1.PUB_HASH_INFO to 32768U,
- TracingModuleV1.PUB_LOG to 16384U,
- TracingModuleV1.PUB_LOG_INFO to 16384U,
- TracingModuleV1.RLP to 512U,
- TracingModuleV1.ROM to 4194304U,
- TracingModuleV1.SHF to 65536U,
- TracingModuleV1.SHF_RT to 4096U,
- TracingModuleV1.TX_RLP to 131072U,
- TracingModuleV1.WCP to 262144U,
- TracingModuleV1.BLOCK_TX to 200U,
- TracingModuleV1.BLOCK_L2L1LOGS to 16U,
- TracingModuleV1.BLOCK_KECCAK to 8192U,
- TracingModuleV1.PRECOMPILE_ECRECOVER to 10000U,
- TracingModuleV1.PRECOMPILE_SHA2 to 10000U,
- TracingModuleV1.PRECOMPILE_RIPEMD to 10000U,
- TracingModuleV1.PRECOMPILE_IDENTITY to 10000U,
- TracingModuleV1.PRECOMPILE_MODEXP to 10000U,
- TracingModuleV1.PRECOMPILE_ECADD to 10000U,
- TracingModuleV1.PRECOMPILE_ECMUL to 10000U,
- TracingModuleV1.PRECOMPILE_ECPAIRING to 10000U,
- TracingModuleV1.PRECOMPILE_BLAKE2F to 512U
- )
- ),
- _tracesLimitsV2 = TracesCountersV2(
- mapOf(
- TracingModuleV2.ADD to 524288u,
- TracingModuleV2.BIN to 262144u,
- TracingModuleV2.BLAKE_MODEXP_DATA to 16384u,
- TracingModuleV2.BLOCK_DATA to 1024u,
- TracingModuleV2.BLOCK_HASH to 512u,
- TracingModuleV2.EC_DATA to 262144u,
- TracingModuleV2.EUC to 65536u,
- TracingModuleV2.EXP to 8192u,
- TracingModuleV2.EXT to 1048576u,
- TracingModuleV2.GAS to 65536u,
- TracingModuleV2.HUB to 2097152u,
- TracingModuleV2.LOG_DATA to 65536u,
- TracingModuleV2.LOG_INFO to 4096u,
- TracingModuleV2.MMIO to 4194304u,
- TracingModuleV2.MMU to 4194304u,
- TracingModuleV2.MOD to 131072u,
- TracingModuleV2.MUL to 65536u,
- TracingModuleV2.MXP to 524288u,
- TracingModuleV2.OOB to 262144u,
- TracingModuleV2.RLP_ADDR to 4096u,
- TracingModuleV2.RLP_TXN to 131072u,
- TracingModuleV2.RLP_TXN_RCPT to 65536u,
- TracingModuleV2.ROM to 4194304u,
- TracingModuleV2.ROM_LEX to 1024u,
- TracingModuleV2.SHAKIRA_DATA to 32768u,
- TracingModuleV2.SHF to 65536u,
- TracingModuleV2.STP to 16384u,
- TracingModuleV2.TRM to 32768u,
- TracingModuleV2.TXN_DATA to 8192u,
- TracingModuleV2.WCP to 262144u,
- TracingModuleV2.BIN_REFERENCE_TABLE to 4294967295u,
- TracingModuleV2.SHF_REFERENCE_TABLE to 4294967295u,
- TracingModuleV2.INSTRUCTION_DECODER to 4294967295u,
- TracingModuleV2.PRECOMPILE_ECRECOVER_EFFECTIVE_CALLS to 128u,
- TracingModuleV2.PRECOMPILE_SHA2_BLOCKS to 671u,
- TracingModuleV2.PRECOMPILE_RIPEMD_BLOCKS to 671u,
- TracingModuleV2.PRECOMPILE_MODEXP_EFFECTIVE_CALLS to 4u,
- TracingModuleV2.PRECOMPILE_ECADD_EFFECTIVE_CALLS to 16384u,
- TracingModuleV2.PRECOMPILE_ECMUL_EFFECTIVE_CALLS to 32u,
- TracingModuleV2.PRECOMPILE_ECPAIRING_FINAL_EXPONENTIATIONS to 16u,
- TracingModuleV2.PRECOMPILE_ECPAIRING_G2_MEMBERSHIP_CALLS to 64u,
- TracingModuleV2.PRECOMPILE_ECPAIRING_MILLER_LOOPS to 64u,
- TracingModuleV2.PRECOMPILE_BLAKE_EFFECTIVE_CALLS to 600u,
- TracingModuleV2.PRECOMPILE_BLAKE_ROUNDS to 600u,
- TracingModuleV2.BLOCK_KECCAK to 8192u,
- TracingModuleV2.BLOCK_L1_SIZE to 1000000u,
- TracingModuleV2.BLOCK_L2_L1_LOGS to 16u,
- TracingModuleV2.BLOCK_TRANSACTIONS to 200u
- )
- ),
+ _tracesLimitsV1 = expectedTracesCountersV1,
+ _tracesLimitsV2 = expectedTracesLimitsV2,
_smartContractErrors = mapOf(
// L1 Linea Rollup
"0f06cd15" to "DataAlreadySubmitted",
"c01eab56" to "EmptySubmissionData",
- "abefa5e8" to "DataStartingBlockDoesNotMatch",
- "5548c6b3" to "DataParentHasEmptyShnarf",
- "36459fa0" to "L1RollingHashDoesNotExistOnL1",
- "cbbd7953" to "FirstBlockGreaterThanFinalBlock",
- "a386ed70" to "FirstBlockLessThanOrEqualToLastFinalizedBlock",
- "70614405" to "FinalBlockNumberLessThanOrEqualToLastFinalizedBlock",
- "2898482a" to "FinalBlockStateEqualsZeroHash",
- "bf81c6e0" to "FinalizationInTheFuture",
- "0c256592" to "MissingMessageNumberForRollingHash",
- "5228f4c8" to "MissingRollingHashForMessageNumber",
- "729eebce" to "FirstByteIsNotZero",
- "6426c6c5" to "BytesLengthNotMultipleOf32",
- "68dcad5f" to "PointEvaluationResponseInvalid",
- "f75db381" to "PrecompileReturnDataLengthWrong",
- "a71194af" to "PointEvaluationFailed",
- "2f22b98a" to "LastFinalizedShnarfWrong",
- "7dc2487d" to "SnarkHashIsZeroHash",
- "bc5aad11" to "FinalizationStateIncorrect",
- "b1504a5f" to "BlobSubmissionDataIsMissing",
- "c0e41e1d" to "EmptyBlobDataAtIndex",
- "fb4cd6ef" to "FinalBlockDoesNotMatchShnarfFinalBlock",
- "2526F108" to "ShnarfAndFinalBlockNumberLengthsMismatched",
- "d3664fb3" to "FinalShnarfWrong",
- "4e686675" to "L2MerkleRootDoesNotExist",
- "e5d14425" to "L2MerkleRootAlreadyAnchored",
- "0c91d776" to "BytesLengthNotMultipleOfTwo",
- "ead4c30e" to "StartingRootHashDoesNotMatch",
- "7907d79b" to "ProofIsEmpty",
- "69ed70ab" to "InvalidProofType",
- "09bde339" to "InvalidProof",
- "db246dde" to "IsPaused",
- "b015579f" to "IsNotPaused",
- "3b174434" to "MessageHashesListLengthHigherThanOneHundred",
- "ca389c44" to "InvalidProofOrProofVerificationRanOutOfGas",
- "42ab979d" to "ParentBlobNotSubmitted",
- "edeae83c" to "FinalBlobNotSubmitted",
- // L2 Message Service
- "6446cc9c" to "MessageHashesListLengthIsZero",
- "d39e75f9" to "L1MessageNumberSynchronizationWrong",
- "7557a60a" to "L1RollingHashSynchronizationWrong",
- "36a4bb94" to "FinalRollingHashIsZero"
+ "abefa5e8" to "DataStartingBlockDoesNotMatch"
),
fetchBlocksLimit = 4000
)
@@ -478,176 +338,7 @@ class CoordinatorConfigTest {
gasPriceCapsCheckCoefficient = 0.9,
historicBaseFeePerBlobGasLowerBound = 100_000_000u,
historicAvgRewardConstant = 100_000_000u,
- timeOfDayMultipliers = mapOf(
- "SUNDAY_0" to 1.7489178377946066,
- "SUNDAY_1" to 1.7494632175198737,
- "SUNDAY_2" to 1.75,
- "SUNDAY_3" to 1.733166295438555,
- "SUNDAY_4" to 1.6993775444542885,
- "SUNDAY_5" to 1.6350086618091364,
- "SUNDAY_6" to 1.5627740860151331,
- "SUNDAY_7" to 1.4831149222064164,
- "SUNDAY_8" to 1.4101476768256929,
- "SUNDAY_9" to 1.370085278922007,
- "SUNDAY_10" to 1.3516015544068651,
- "SUNDAY_11" to 1.3482404546676368,
- "SUNDAY_12" to 1.3580905751578942,
- "SUNDAY_13" to 1.3775497419563296,
- "SUNDAY_14" to 1.3700255667542938,
- "SUNDAY_15" to 1.2642948506461285,
- "SUNDAY_16" to 1.2794806131912935,
- "SUNDAY_17" to 1.2750892256476676,
- "SUNDAY_18" to 1.2919720208955585,
- "SUNDAY_19" to 1.317984990098603,
- "SUNDAY_20" to 1.4433501639513178,
- "SUNDAY_21" to 1.4705921238901998,
- "SUNDAY_22" to 1.515043370430801,
- "SUNDAY_23" to 1.5556742617266397,
- "MONDAY_0" to 1.5381562278760164,
- "MONDAY_1" to 1.5423761828433993,
- "MONDAY_2" to 1.539015963719092,
- "MONDAY_3" to 1.487676153648977,
- "MONDAY_4" to 1.430973985132037,
- "MONDAY_5" to 1.4656765439056292,
- "MONDAY_6" to 1.4484298622828233,
- "MONDAY_7" to 1.4459076216659752,
- "MONDAY_8" to 1.4899061835032241,
- "MONDAY_9" to 1.5249733712852067,
- "MONDAY_10" to 1.511367489481033,
- "MONDAY_11" to 1.4225695658047797,
- "MONDAY_12" to 1.2887291896624584,
- "MONDAY_13" to 1.1460926897291355,
- "MONDAY_14" to 1.0004897955233254,
- "MONDAY_15" to 0.8694664537368378,
- "MONDAY_16" to 0.8270273375962802,
- "MONDAY_17" to 0.7868289022833883,
- "MONDAY_18" to 0.7780303121746551,
- "MONDAY_19" to 0.7756215256634205,
- "MONDAY_20" to 0.7984895728860915,
- "MONDAY_21" to 0.8918589268832423,
- "MONDAY_22" to 0.9967716668541272,
- "MONDAY_23" to 1.0973334887144106,
- "TUESDAY_0" to 1.2233064209957951,
- "TUESDAY_1" to 1.3238883432855082,
- "TUESDAY_2" to 1.3874518307497257,
- "TUESDAY_3" to 1.463621147171298,
- "TUESDAY_4" to 1.4975989065490154,
- "TUESDAY_5" to 1.481679186141442,
- "TUESDAY_6" to 1.452778387763161,
- "TUESDAY_7" to 1.3414858185569951,
- "TUESDAY_8" to 1.2869454637983988,
- "TUESDAY_9" to 1.249347290389873,
- "TUESDAY_10" to 1.196488297386161,
- "TUESDAY_11" to 1.1136140507034202,
- "TUESDAY_12" to 0.9867528660797885,
- "TUESDAY_13" to 0.8018989158195754,
- "TUESDAY_14" to 0.6173048748109258,
- "TUESDAY_15" to 0.46718586671750373,
- "TUESDAY_16" to 0.4103633833041902,
- "TUESDAY_17" to 0.4871260756989506,
- "TUESDAY_18" to 0.5667378483016126,
- "TUESDAY_19" to 0.6464203510900723,
- "TUESDAY_20" to 0.7780268325299871,
- "TUESDAY_21" to 0.8995921101255763,
- "TUESDAY_22" to 1.0077600114996088,
- "TUESDAY_23" to 1.1109769960680498,
- "WEDNESDAY_0" to 1.2097668746150059,
- "WEDNESDAY_1" to 1.2631002319009361,
- "WEDNESDAY_2" to 1.2912775191940549,
- "WEDNESDAY_3" to 1.3229785939630059,
- "WEDNESDAY_4" to 1.3428607301494424,
- "WEDNESDAY_5" to 1.3750788517823973,
- "WEDNESDAY_6" to 1.3752344527256497,
- "WEDNESDAY_7" to 1.3505490078766218,
- "WEDNESDAY_8" to 1.2598503219367945,
- "WEDNESDAY_9" to 1.2051668977452374,
- "WEDNESDAY_10" to 1.0320896222195326,
- "WEDNESDAY_11" to 0.8900138031631949,
- "WEDNESDAY_12" to 0.6341155208698448,
- "WEDNESDAY_13" to 0.48337590254714624,
- "WEDNESDAY_14" to 0.2903189399226416,
- "WEDNESDAY_15" to 0.25,
- "WEDNESDAY_16" to 0.25711039485046006,
- "WEDNESDAY_17" to 0.37307641907591793,
- "WEDNESDAY_18" to 0.45280799454961196,
- "WEDNESDAY_19" to 0.5631397823847637,
- "WEDNESDAY_20" to 0.6285005244224133,
- "WEDNESDAY_21" to 0.6671897537279405,
- "WEDNESDAY_22" to 0.7268406397452634,
- "WEDNESDAY_23" to 0.8068904097486369,
- "THURSDAY_0" to 0.9021601102971811,
- "THURSDAY_1" to 1.023741688964238,
- "THURSDAY_2" to 1.1340689935096755,
- "THURSDAY_3" to 1.2530130345819006,
- "THURSDAY_4" to 1.3163421664973542,
- "THURSDAY_5" to 1.3536343767230727,
- "THURSDAY_6" to 1.3432290485306728,
- "THURSDAY_7" to 1.2864983218982178,
- "THURSDAY_8" to 1.2320488534113174,
- "THURSDAY_9" to 1.1984530721079034,
- "THURSDAY_10" to 1.0877338251341975,
- "THURSDAY_11" to 0.9999324929016475,
- "THURSDAY_12" to 0.87536726762619,
- "THURSDAY_13" to 0.6560822412167919,
- "THURSDAY_14" to 0.44836474861432074,
- "THURSDAY_15" to 0.36145134935025247,
- "THURSDAY_16" to 0.2695997829759713,
- "THURSDAY_17" to 0.2898426312618241,
- "THURSDAY_18" to 0.3970093434340387,
- "THURSDAY_19" to 0.5193273246848977,
- "THURSDAY_20" to 0.6426415257034419,
- "THURSDAY_21" to 0.800685718218497,
- "THURSDAY_22" to 0.9215516833839711,
- "THURSDAY_23" to 1.053701659160912,
- "FRIDAY_0" to 1.149649788723893,
- "FRIDAY_1" to 1.2046315447861193,
- "FRIDAY_2" to 1.2724031281576726,
- "FRIDAY_3" to 1.3525693456352732,
- "FRIDAY_4" to 1.3746126314960814,
- "FRIDAY_5" to 1.3744591862592468,
- "FRIDAY_6" to 1.3297812543035683,
- "FRIDAY_7" to 1.2762064429631657,
- "FRIDAY_8" to 1.235662409263294,
- "FRIDAY_9" to 1.2171558028785991,
- "FRIDAY_10" to 1.182722399785398,
- "FRIDAY_11" to 1.137345538963285,
- "FRIDAY_12" to 0.9999308422620752,
- "FRIDAY_13" to 0.8055000309055653,
- "FRIDAY_14" to 0.5667135273493851,
- "FRIDAY_15" to 0.4081529603000651,
- "FRIDAY_16" to 0.3987031354907009,
- "FRIDAY_17" to 0.5030075499003412,
- "FRIDAY_18" to 0.6518159532641841,
- "FRIDAY_19" to 0.8733483414970974,
- "FRIDAY_20" to 1.0496224913080463,
- "FRIDAY_21" to 1.1820684558591705,
- "FRIDAY_22" to 1.2561688567574458,
- "FRIDAY_23" to 1.3204704912328773,
- "SATURDAY_0" to 1.3832230236620218,
- "SATURDAY_1" to 1.4632908341022142,
- "SATURDAY_2" to 1.5019230781315296,
- "SATURDAY_3" to 1.5437332506007084,
- "SATURDAY_4" to 1.5934153179751855,
- "SATURDAY_5" to 1.6245578072557723,
- "SATURDAY_6" to 1.6294919789890665,
- "SATURDAY_7" to 1.6027665451672717,
- "SATURDAY_8" to 1.6068061069158674,
- "SATURDAY_9" to 1.624257927970777,
- "SATURDAY_10" to 1.5996112411089,
- "SATURDAY_11" to 1.5659672993092648,
- "SATURDAY_12" to 1.5333537902522736,
- "SATURDAY_13" to 1.445292929996356,
- "SATURDAY_14" to 1.2966021477035259,
- "SATURDAY_15" to 1.250999408961155,
- "SATURDAY_16" to 1.2535364828163025,
- "SATURDAY_17" to 1.2736456128871074,
- "SATURDAY_18" to 1.3348268054897328,
- "SATURDAY_19" to 1.4571388900094875,
- "SATURDAY_20" to 1.5073787902995706,
- "SATURDAY_21" to 1.5605139580010123,
- "SATURDAY_22" to 1.5885303316932382,
- "SATURDAY_23" to 1.6169891066719597
- )
+ timeOfDayMultipliers = expectedTimeOfDayMultipliers
),
feeHistoryFetcher = L1DynamicGasPriceCapServiceConfig.FeeHistoryFetcher(
fetchInterval = Duration.parse("PT1S"),
@@ -689,201 +380,141 @@ class CoordinatorConfigTest {
private data class TestConfig(val extraField: String)
@Test
- fun parsesValidConfig() {
- val smartContractErrorConfig =
- CoordinatorAppCli.loadConfigsOrError(
- listOf(File("../../config/common/smart-contract-errors.toml"))
- )
- val timeOfDayMultipliers =
- CoordinatorAppCli.loadConfigsOrError(
- listOf(File("../../config/common/gas-price-cap-time-of-day-multipliers.toml"))
- )
- val tracesLimitsConfigs =
- CoordinatorAppCli.loadConfigsOrError(
- listOf(File("../../config/common/traces-limits-v1.toml"))
- )
- val tracesLimitsV2Configs =
- CoordinatorAppCli.loadConfigsOrError(
- listOf(File("../../config/common/traces-limits-v2.toml"))
- )
- CoordinatorAppCli.loadConfigsOrError(
- listOf(File("../../config/coordinator/coordinator-docker.config.toml"))
- )
- .onFailure { error: String -> fail(error) }
- .onSuccess { config: CoordinatorConfigTomlDto ->
- val configs = config.copy(
- conflation = config.conflation.copy(
- _tracesLimitsV1 = tracesLimitsConfigs.get()?.tracesLimits?.let { TracesCountersV1(it) },
- _tracesLimitsV2 = tracesLimitsV2Configs.get()?.tracesLimits?.let { TracesCountersV2(it) },
- _smartContractErrors = smartContractErrorConfig.get()!!.smartContractErrors
- ),
- l1DynamicGasPriceCapService = config.l1DynamicGasPriceCapService.copy(
- gasPriceCapCalculation = config.l1DynamicGasPriceCapService.gasPriceCapCalculation.copy(
- timeOfDayMultipliers = timeOfDayMultipliers.get()?.gasPriceCapTimeOfDayMultipliers
- )
- )
- )
- assertEquals(coordinatorConfig, configs.reified())
- assertEquals(coordinatorConfig.l1.rpcEndpoint, coordinatorConfig.l1.ethFeeHistoryEndpoint)
- }
+ fun `should keep local stack testing configs uptodate with the code`() {
+ // Just assert that Files have been loaded and parsed correctly
+ // This is to prevent Code changes in coordinator and forgetting to update config files used in the local stack
+ loadConfigs(
+ coordinatorConfigFiles = listOf(
+ Path.of("../../config/coordinator/coordinator-docker.config.toml"),
+ Path.of("../../config/coordinator/coordinator-docker-traces-v2-override.config.toml"),
+ Path.of("../../config/coordinator/coordinator-docker-web3signer-override.config.toml"),
+ Path.of("../../config/coordinator/coordinator-local-dev.config.overrides.toml"),
+ Path.of("../../config/coordinator/coordinator-local-dev.config-traces-v2.overrides.toml")
+ ),
+ tracesLimitsFileV1 = Path.of("../../config/common/traces-limits-v1.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")
+ )
+ }
+
+ private fun pathToResource(resource: String): Path {
+ return Paths.get(
+ this::class.java.classLoader.getResource(resource)?.toURI()
+ ?: error("Resource not found: $resource")
+ )
}
@Test
- fun parsesValidWeb3SignerConfigOverride() {
- val smartContractErrorCodes: SmartContractErrors =
- CoordinatorAppCli.loadConfigsOrError(
- listOf(File("../../config/common/smart-contract-errors.toml"))
- ).get()!!.smartContractErrors
- val timeOfDayMultipliers =
- CoordinatorAppCli.loadConfigsOrError(
- listOf(File("../../config/common/gas-price-cap-time-of-day-multipliers.toml"))
- )
- val tracesLimitsConfigs =
- CoordinatorAppCli.loadConfigsOrError(
- listOf(File("../../config/common/traces-limits-v1.toml"))
- )
- val tracesLimitsV2Configs =
- CoordinatorAppCli.loadConfigsOrError(
- listOf(File("../../config/common/traces-limits-v2.toml"))
- )
+ fun `should parse and consolidate configs`() {
+ val configs = loadConfigs(
+ coordinatorConfigFiles = listOf(pathToResource("configs/coordinator.config.toml")),
+ tracesLimitsFileV1 = pathToResource("configs/traces-limits-v1.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")
+ )
- CoordinatorAppCli.loadConfigsOrError(
- listOf(
- File("../../config/coordinator/coordinator-docker.config.toml"),
- File("../../config/coordinator/coordinator-docker-web3signer-override.config.toml")
- )
+ assertEquals(coordinatorConfig, configs)
+ assertEquals(coordinatorConfig.l1.rpcEndpoint, coordinatorConfig.l1.ethFeeHistoryEndpoint)
+ }
+
+ @Test
+ fun parsesValidWeb3SignerConfigOverride() {
+ val config = loadConfigs(
+ coordinatorConfigFiles = listOf(
+ pathToResource("configs/coordinator.config.toml"),
+ pathToResource("configs/coordinator-web3signer-override.config.toml")
+ ),
+ tracesLimitsFileV1 = pathToResource("configs/traces-limits-v1.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")
)
- .onFailure { error: String -> fail(error) }
- .onSuccess {
- val configs = it.copy(
- conflation = it.conflation.copy(
- _tracesLimitsV1 = tracesLimitsConfigs.get()?.tracesLimits?.let { TracesCountersV1(it) },
- _tracesLimitsV2 = tracesLimitsV2Configs.get()?.tracesLimits?.let { TracesCountersV2(it) },
- _smartContractErrors = smartContractErrorCodes
- ),
- l1DynamicGasPriceCapService = it.l1DynamicGasPriceCapService.copy(
- gasPriceCapCalculation = it.l1DynamicGasPriceCapService.gasPriceCapCalculation.copy(
- timeOfDayMultipliers = timeOfDayMultipliers.get()?.gasPriceCapTimeOfDayMultipliers
- )
- )
- )
- 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)
- )
+ 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)
+ )
- assertEquals(expectedConfig, configs.reified())
- }
+ assertThat(config).isEqualTo(expectedConfig)
}
@Test
fun parsesValidTracesV2ConfigOverride() {
- val smartContractErrorCodes: SmartContractErrors =
- CoordinatorAppCli.loadConfigsOrError(
- listOf(File("../../config/common/smart-contract-errors.toml"))
- ).get()!!.smartContractErrors
- val timeOfDayMultipliers =
- CoordinatorAppCli.loadConfigsOrError(
- listOf(File("../../config/common/gas-price-cap-time-of-day-multipliers.toml"))
- )
- val tracesLimitsConfigs =
- CoordinatorAppCli.loadConfigsOrError(
- listOf(File("../../config/common/traces-limits-v1.toml"))
- )
- val tracesLimitsV2Configs =
- CoordinatorAppCli.loadConfigsOrError(
- listOf(File("../../config/common/traces-limits-v2.toml"))
- )
-
- CoordinatorAppCli.loadConfigsOrError(
- listOf(
- File("../../config/coordinator/coordinator-docker.config.toml"),
- File("../../config/coordinator/coordinator-docker-traces-v2-override.config.toml")
- )
+ val config = loadConfigs(
+ coordinatorConfigFiles = listOf(
+ pathToResource("configs/coordinator.config.toml"),
+ pathToResource("configs/coordinator-traces-v2-override.config.toml")
+ ),
+ tracesLimitsFileV1 = pathToResource("configs/traces-limits-v1.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")
)
- .onFailure { error: String -> fail(error) }
- .onSuccess {
- val configs = it.copy(
- conflation = it.conflation.copy(
- _tracesLimitsV1 = tracesLimitsConfigs.get()?.tracesLimits?.let { TracesCountersV1(it) },
- _tracesLimitsV2 = tracesLimitsV2Configs.get()?.tracesLimits?.let { TracesCountersV2(it) },
- _smartContractErrors = smartContractErrorCodes
+
+ val expectedConfig =
+ coordinatorConfig.copy(
+ zkTraces = zkTracesConfig.copy(ethApi = URI("http://traces-node-v2:8545").toURL()),
+ l2NetworkGasPricingService = l2NetworkGasPricingServiceConfig.copy(
+ legacy =
+ l2NetworkGasPricingServiceConfig.legacy.copy(
+ transactionCostCalculatorConfig =
+ l2NetworkGasPricingServiceConfig.legacy.transactionCostCalculatorConfig?.copy(
+ compressedTxSize = 350,
+ expectedGas = 29400
+ )
+ )
+ ),
+ traces = tracesConfig.copy(
+ switchToLineaBesu = true,
+ blobCompressorVersion = BlobCompressorVersion.V1_0_1,
+ expectedTracesApiVersionV2 = "v0.8.0-rc8",
+ conflationV2 = tracesConfig.conflation.copy(
+ endpoints = listOf(URI("http://traces-node-v2:8545/").toURL()),
+ requestLimitPerEndpoint = 1U
),
- l1DynamicGasPriceCapService = it.l1DynamicGasPriceCapService.copy(
- gasPriceCapCalculation = it.l1DynamicGasPriceCapService.gasPriceCapCalculation.copy(
- timeOfDayMultipliers = timeOfDayMultipliers.get()?.gasPriceCapTimeOfDayMultipliers
+ countersV2 = TracesConfig.FunctionalityEndpoint(
+ listOf(
+ URI("http://traces-node-v2:8545/").toURL()
+ ),
+ requestLimitPerEndpoint = 1U,
+ requestRetry = RequestRetryConfigTomlFriendly(
+ backoffDelay = Duration.parse("PT1S"),
+ failuresWarningThreshold = 2
)
)
- )
-
- val expectedConfig =
- coordinatorConfig.copy(
- zkTraces = zkTracesConfig.copy(ethApi = URI("http://traces-node-v2:8545").toURL()),
- l2NetworkGasPricingService = l2NetworkGasPricingServiceConfig.copy(
- legacy =
- l2NetworkGasPricingServiceConfig.legacy.copy(
- transactionCostCalculatorConfig =
- l2NetworkGasPricingServiceConfig.legacy.transactionCostCalculatorConfig?.copy(
- compressedTxSize = 350,
- expectedGas = 29400
- )
- )
+ ),
+ 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")
),
- traces = tracesConfig.copy(
- switchToLineaBesu = true,
- blobCompressorVersion = BlobCompressorVersion.V1_0_1,
- expectedTracesApiVersionV2 = "v0.8.0-rc8",
- conflationV2 = tracesConfig.conflation.copy(
- endpoints = listOf(URI("http://traces-node-v2:8545/").toURL()),
- requestLimitPerEndpoint = 1U
- ),
- countersV2 = TracesConfig.FunctionalityEndpoint(
- listOf(
- URI("http://traces-node-v2:8545/").toURL()
- ),
- requestLimitPerEndpoint = 1U,
- requestRetry = RequestRetryConfigTomlFriendly(
- backoffDelay = Duration.parse("PT1S"),
- failuresWarningThreshold = 2
- )
- )
+ blobCompression = proversConfig.proverA.blobCompression.copy(
+ requestsDirectory = Path.of("/data/prover/v3/compression/requests"),
+ responsesDirectory = Path.of("/data/prover/v3/compression/responses")
),
- 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")
- ),
- blobCompression = proversConfig.proverA.blobCompression.copy(
- requestsDirectory = Path.of("/data/prover/v3/compression/requests"),
- 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")
- )
- )
+ proofAggregation = proversConfig.proverA.proofAggregation.copy(
+ requestsDirectory = Path.of("/data/prover/v3/aggregation/requests"),
+ responsesDirectory = Path.of("/data/prover/v3/aggregation/responses")
)
)
+ )
+ )
- assertEquals(expectedConfig, configs.reified())
- }
+ assertThat(config).isEqualTo(expectedConfig)
}
@Test
fun invalidConfigReturnsErrorResult() {
- val configs =
- CoordinatorAppCli.loadConfigsOrError(
- listOf(
- File("../../config/coordinator/coordinator-docker.config.toml"),
- File("../../config/coordinator/coordinator-docker-web3signer-override.config.toml")
- )
- )
+ val configsResult = loadConfigsOrError(
+ configFiles = listOf(pathToResource("configs/coordinator.config.toml"))
+ )
- assertThat(configs.getError()).contains("'extraField': Missing from config")
+ assertThat(configsResult.getError()).contains("'extraField': Missing from config")
}
@Test
@@ -930,8 +561,7 @@ class CoordinatorConfigTest {
}
@Test
- fun testValidAggregationAndConflationByTargetBlockNumberWhenL2InclusiveBlockNumberToStopAndFlushAggregationSpecified
- () {
+ fun testValidAggrAndConflationByTargetBlockNumberWhenL2InclusiveBlockNumberToStopAndFlushAggregationSpecified() {
val aggregationConfigWithoutSwithBlockNumber = aggregationConfig.copy(
_targetEndBlocks = listOf(10L, 100L)
)
diff --git a/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/ExpectedGasPriceMultipliers.kt b/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/ExpectedGasPriceMultipliers.kt
new file mode 100644
index 000000000..d872e96a1
--- /dev/null
+++ b/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/ExpectedGasPriceMultipliers.kt
@@ -0,0 +1,172 @@
+package net.consensys.zkevm.coordinator.app.config
+
+val expectedTimeOfDayMultipliers = mapOf(
+ "SUNDAY_0" to 1.7489178377946066,
+ "SUNDAY_1" to 1.7494632175198737,
+ "SUNDAY_2" to 1.75,
+ "SUNDAY_3" to 1.733166295438555,
+ "SUNDAY_4" to 1.6993775444542885,
+ "SUNDAY_5" to 1.6350086618091364,
+ "SUNDAY_6" to 1.5627740860151331,
+ "SUNDAY_7" to 1.4831149222064164,
+ "SUNDAY_8" to 1.4101476768256929,
+ "SUNDAY_9" to 1.370085278922007,
+ "SUNDAY_10" to 1.3516015544068651,
+ "SUNDAY_11" to 1.3482404546676368,
+ "SUNDAY_12" to 1.3580905751578942,
+ "SUNDAY_13" to 1.3775497419563296,
+ "SUNDAY_14" to 1.3700255667542938,
+ "SUNDAY_15" to 1.2642948506461285,
+ "SUNDAY_16" to 1.2794806131912935,
+ "SUNDAY_17" to 1.2750892256476676,
+ "SUNDAY_18" to 1.2919720208955585,
+ "SUNDAY_19" to 1.317984990098603,
+ "SUNDAY_20" to 1.4433501639513178,
+ "SUNDAY_21" to 1.4705921238901998,
+ "SUNDAY_22" to 1.515043370430801,
+ "SUNDAY_23" to 1.5556742617266397,
+ "MONDAY_0" to 1.5381562278760164,
+ "MONDAY_1" to 1.5423761828433993,
+ "MONDAY_2" to 1.539015963719092,
+ "MONDAY_3" to 1.487676153648977,
+ "MONDAY_4" to 1.430973985132037,
+ "MONDAY_5" to 1.4656765439056292,
+ "MONDAY_6" to 1.4484298622828233,
+ "MONDAY_7" to 1.4459076216659752,
+ "MONDAY_8" to 1.4899061835032241,
+ "MONDAY_9" to 1.5249733712852067,
+ "MONDAY_10" to 1.511367489481033,
+ "MONDAY_11" to 1.4225695658047797,
+ "MONDAY_12" to 1.2887291896624584,
+ "MONDAY_13" to 1.1460926897291355,
+ "MONDAY_14" to 1.0004897955233254,
+ "MONDAY_15" to 0.8694664537368378,
+ "MONDAY_16" to 0.8270273375962802,
+ "MONDAY_17" to 0.7868289022833883,
+ "MONDAY_18" to 0.7780303121746551,
+ "MONDAY_19" to 0.7756215256634205,
+ "MONDAY_20" to 0.7984895728860915,
+ "MONDAY_21" to 0.8918589268832423,
+ "MONDAY_22" to 0.9967716668541272,
+ "MONDAY_23" to 1.0973334887144106,
+ "TUESDAY_0" to 1.2233064209957951,
+ "TUESDAY_1" to 1.3238883432855082,
+ "TUESDAY_2" to 1.3874518307497257,
+ "TUESDAY_3" to 1.463621147171298,
+ "TUESDAY_4" to 1.4975989065490154,
+ "TUESDAY_5" to 1.481679186141442,
+ "TUESDAY_6" to 1.452778387763161,
+ "TUESDAY_7" to 1.3414858185569951,
+ "TUESDAY_8" to 1.2869454637983988,
+ "TUESDAY_9" to 1.249347290389873,
+ "TUESDAY_10" to 1.196488297386161,
+ "TUESDAY_11" to 1.1136140507034202,
+ "TUESDAY_12" to 0.9867528660797885,
+ "TUESDAY_13" to 0.8018989158195754,
+ "TUESDAY_14" to 0.6173048748109258,
+ "TUESDAY_15" to 0.46718586671750373,
+ "TUESDAY_16" to 0.4103633833041902,
+ "TUESDAY_17" to 0.4871260756989506,
+ "TUESDAY_18" to 0.5667378483016126,
+ "TUESDAY_19" to 0.6464203510900723,
+ "TUESDAY_20" to 0.7780268325299871,
+ "TUESDAY_21" to 0.8995921101255763,
+ "TUESDAY_22" to 1.0077600114996088,
+ "TUESDAY_23" to 1.1109769960680498,
+ "WEDNESDAY_0" to 1.2097668746150059,
+ "WEDNESDAY_1" to 1.2631002319009361,
+ "WEDNESDAY_2" to 1.2912775191940549,
+ "WEDNESDAY_3" to 1.3229785939630059,
+ "WEDNESDAY_4" to 1.3428607301494424,
+ "WEDNESDAY_5" to 1.3750788517823973,
+ "WEDNESDAY_6" to 1.3752344527256497,
+ "WEDNESDAY_7" to 1.3505490078766218,
+ "WEDNESDAY_8" to 1.2598503219367945,
+ "WEDNESDAY_9" to 1.2051668977452374,
+ "WEDNESDAY_10" to 1.0320896222195326,
+ "WEDNESDAY_11" to 0.8900138031631949,
+ "WEDNESDAY_12" to 0.6341155208698448,
+ "WEDNESDAY_13" to 0.48337590254714624,
+ "WEDNESDAY_14" to 0.2903189399226416,
+ "WEDNESDAY_15" to 0.25,
+ "WEDNESDAY_16" to 0.25711039485046006,
+ "WEDNESDAY_17" to 0.37307641907591793,
+ "WEDNESDAY_18" to 0.45280799454961196,
+ "WEDNESDAY_19" to 0.5631397823847637,
+ "WEDNESDAY_20" to 0.6285005244224133,
+ "WEDNESDAY_21" to 0.6671897537279405,
+ "WEDNESDAY_22" to 0.7268406397452634,
+ "WEDNESDAY_23" to 0.8068904097486369,
+ "THURSDAY_0" to 0.9021601102971811,
+ "THURSDAY_1" to 1.023741688964238,
+ "THURSDAY_2" to 1.1340689935096755,
+ "THURSDAY_3" to 1.2530130345819006,
+ "THURSDAY_4" to 1.3163421664973542,
+ "THURSDAY_5" to 1.3536343767230727,
+ "THURSDAY_6" to 1.3432290485306728,
+ "THURSDAY_7" to 1.2864983218982178,
+ "THURSDAY_8" to 1.2320488534113174,
+ "THURSDAY_9" to 1.1984530721079034,
+ "THURSDAY_10" to 1.0877338251341975,
+ "THURSDAY_11" to 0.9999324929016475,
+ "THURSDAY_12" to 0.87536726762619,
+ "THURSDAY_13" to 0.6560822412167919,
+ "THURSDAY_14" to 0.44836474861432074,
+ "THURSDAY_15" to 0.36145134935025247,
+ "THURSDAY_16" to 0.2695997829759713,
+ "THURSDAY_17" to 0.2898426312618241,
+ "THURSDAY_18" to 0.3970093434340387,
+ "THURSDAY_19" to 0.5193273246848977,
+ "THURSDAY_20" to 0.6426415257034419,
+ "THURSDAY_21" to 0.800685718218497,
+ "THURSDAY_22" to 0.9215516833839711,
+ "THURSDAY_23" to 1.053701659160912,
+ "FRIDAY_0" to 1.149649788723893,
+ "FRIDAY_1" to 1.2046315447861193,
+ "FRIDAY_2" to 1.2724031281576726,
+ "FRIDAY_3" to 1.3525693456352732,
+ "FRIDAY_4" to 1.3746126314960814,
+ "FRIDAY_5" to 1.3744591862592468,
+ "FRIDAY_6" to 1.3297812543035683,
+ "FRIDAY_7" to 1.2762064429631657,
+ "FRIDAY_8" to 1.235662409263294,
+ "FRIDAY_9" to 1.2171558028785991,
+ "FRIDAY_10" to 1.182722399785398,
+ "FRIDAY_11" to 1.137345538963285,
+ "FRIDAY_12" to 0.9999308422620752,
+ "FRIDAY_13" to 0.8055000309055653,
+ "FRIDAY_14" to 0.5667135273493851,
+ "FRIDAY_15" to 0.4081529603000651,
+ "FRIDAY_16" to 0.3987031354907009,
+ "FRIDAY_17" to 0.5030075499003412,
+ "FRIDAY_18" to 0.6518159532641841,
+ "FRIDAY_19" to 0.8733483414970974,
+ "FRIDAY_20" to 1.0496224913080463,
+ "FRIDAY_21" to 1.1820684558591705,
+ "FRIDAY_22" to 1.2561688567574458,
+ "FRIDAY_23" to 1.3204704912328773,
+ "SATURDAY_0" to 1.3832230236620218,
+ "SATURDAY_1" to 1.4632908341022142,
+ "SATURDAY_2" to 1.5019230781315296,
+ "SATURDAY_3" to 1.5437332506007084,
+ "SATURDAY_4" to 1.5934153179751855,
+ "SATURDAY_5" to 1.6245578072557723,
+ "SATURDAY_6" to 1.6294919789890665,
+ "SATURDAY_7" to 1.6027665451672717,
+ "SATURDAY_8" to 1.6068061069158674,
+ "SATURDAY_9" to 1.624257927970777,
+ "SATURDAY_10" to 1.5996112411089,
+ "SATURDAY_11" to 1.5659672993092648,
+ "SATURDAY_12" to 1.5333537902522736,
+ "SATURDAY_13" to 1.445292929996356,
+ "SATURDAY_14" to 1.2966021477035259,
+ "SATURDAY_15" to 1.250999408961155,
+ "SATURDAY_16" to 1.2535364828163025,
+ "SATURDAY_17" to 1.2736456128871074,
+ "SATURDAY_18" to 1.3348268054897328,
+ "SATURDAY_19" to 1.4571388900094875,
+ "SATURDAY_20" to 1.5073787902995706,
+ "SATURDAY_21" to 1.5605139580010123,
+ "SATURDAY_22" to 1.5885303316932382,
+ "SATURDAY_23" to 1.6169891066719597
+)
diff --git a/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/ExpectedTracesLimitsV1.kt b/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/ExpectedTracesLimitsV1.kt
new file mode 100644
index 000000000..f9ac7b943
--- /dev/null
+++ b/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/ExpectedTracesLimitsV1.kt
@@ -0,0 +1,48 @@
+package net.consensys.zkevm.coordinator.app.config
+
+import net.consensys.linea.traces.TracesCountersV1
+import net.consensys.linea.traces.TracingModuleV1
+
+val expectedTracesCountersV1 = TracesCountersV1(
+ mapOf(
+ // EVM Arithmetization Limits
+ TracingModuleV1.ADD to 1U,
+ TracingModuleV1.BIN to 2U,
+ TracingModuleV1.BIN_RT to 3U,
+ TracingModuleV1.EC_DATA to 4U,
+ TracingModuleV1.EXT to 5U,
+ TracingModuleV1.HUB to 6U,
+ TracingModuleV1.INSTRUCTION_DECODER to 7U,
+ TracingModuleV1.MMIO to 8U,
+ TracingModuleV1.MMU to 9U,
+ TracingModuleV1.MMU_ID to 10U,
+ TracingModuleV1.MOD to 11U,
+ TracingModuleV1.MUL to 12U,
+ TracingModuleV1.MXP to 13U,
+ TracingModuleV1.PHONEY_RLP to 14U,
+ TracingModuleV1.PUB_HASH to 15U,
+ TracingModuleV1.PUB_HASH_INFO to 16U,
+ TracingModuleV1.PUB_LOG to 17U,
+ TracingModuleV1.PUB_LOG_INFO to 18U,
+ TracingModuleV1.RLP to 19U,
+ TracingModuleV1.ROM to 20U,
+ TracingModuleV1.SHF to 21U,
+ TracingModuleV1.SHF_RT to 22U,
+ TracingModuleV1.TX_RLP to 23U,
+ TracingModuleV1.WCP to 24U,
+ // Block Limits
+ TracingModuleV1.BLOCK_TX to 25U,
+ TracingModuleV1.BLOCK_L2L1LOGS to 26U,
+ TracingModuleV1.BLOCK_KECCAK to 27U,
+ // Precompile Limits
+ TracingModuleV1.PRECOMPILE_ECRECOVER to 28U,
+ TracingModuleV1.PRECOMPILE_SHA2 to 29U,
+ TracingModuleV1.PRECOMPILE_RIPEMD to 30U,
+ TracingModuleV1.PRECOMPILE_IDENTITY to 31U,
+ TracingModuleV1.PRECOMPILE_MODEXP to 32U,
+ TracingModuleV1.PRECOMPILE_ECADD to 32U,
+ TracingModuleV1.PRECOMPILE_ECMUL to 34U,
+ TracingModuleV1.PRECOMPILE_ECPAIRING to 35U,
+ TracingModuleV1.PRECOMPILE_BLAKE2F to 36U
+ )
+)
diff --git a/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/ExpectedTracesLimitsV2.kt b/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/ExpectedTracesLimitsV2.kt
new file mode 100644
index 000000000..82f6447f9
--- /dev/null
+++ b/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/config/ExpectedTracesLimitsV2.kt
@@ -0,0 +1,60 @@
+package net.consensys.zkevm.coordinator.app.config
+
+import net.consensys.linea.traces.TracesCountersV2
+import net.consensys.linea.traces.TracingModuleV2
+
+val expectedTracesLimitsV2 = TracesCountersV2(
+ mapOf(
+ TracingModuleV2.ADD to 1u,
+ TracingModuleV2.BIN to 2u,
+ TracingModuleV2.BLAKE_MODEXP_DATA to 3u,
+ TracingModuleV2.BLOCK_DATA to 4u,
+ TracingModuleV2.BLOCK_HASH to 5u,
+ TracingModuleV2.EC_DATA to 6u,
+ TracingModuleV2.EUC to 7u,
+ TracingModuleV2.EXP to 8u,
+ TracingModuleV2.EXT to 9u,
+ TracingModuleV2.GAS to 10u,
+ TracingModuleV2.HUB to 11u,
+ TracingModuleV2.LOG_DATA to 12u,
+ TracingModuleV2.LOG_INFO to 13u,
+ TracingModuleV2.MMIO to 14u,
+ TracingModuleV2.MMU to 15u,
+ TracingModuleV2.MOD to 16u,
+ TracingModuleV2.MUL to 18u,
+ TracingModuleV2.MXP to 19u,
+ TracingModuleV2.OOB to 20u,
+ TracingModuleV2.RLP_ADDR to 21u,
+ TracingModuleV2.RLP_TXN to 22u,
+ TracingModuleV2.RLP_TXN_RCPT to 23u,
+ TracingModuleV2.ROM to 24u,
+ TracingModuleV2.ROM_LEX to 25u,
+ TracingModuleV2.SHAKIRA_DATA to 26u,
+ TracingModuleV2.SHF to 27u,
+ TracingModuleV2.STP to 28u,
+ TracingModuleV2.TRM to 29u,
+ TracingModuleV2.TXN_DATA to 30u,
+ TracingModuleV2.WCP to 31u,
+ // Reference table limits, set to UInt.MAX_VALUE
+ TracingModuleV2.BIN_REFERENCE_TABLE to 32u,
+ TracingModuleV2.INSTRUCTION_DECODER to 33u,
+ TracingModuleV2.SHF_REFERENCE_TABLE to 34u,
+ // Precompiles limits
+ TracingModuleV2.PRECOMPILE_BLAKE_EFFECTIVE_CALLS to 35u,
+ TracingModuleV2.PRECOMPILE_BLAKE_ROUNDS to 36u,
+ TracingModuleV2.PRECOMPILE_ECADD_EFFECTIVE_CALLS to 37u,
+ TracingModuleV2.PRECOMPILE_ECMUL_EFFECTIVE_CALLS to 38u,
+ TracingModuleV2.PRECOMPILE_ECPAIRING_FINAL_EXPONENTIATIONS to 39u,
+ TracingModuleV2.PRECOMPILE_ECPAIRING_G2_MEMBERSHIP_CALLS to 40u,
+ TracingModuleV2.PRECOMPILE_ECPAIRING_MILLER_LOOPS to 41u,
+ TracingModuleV2.PRECOMPILE_ECRECOVER_EFFECTIVE_CALLS to 42u,
+ TracingModuleV2.PRECOMPILE_MODEXP_EFFECTIVE_CALLS to 43u,
+ TracingModuleV2.PRECOMPILE_RIPEMD_BLOCKS to 44u,
+ TracingModuleV2.PRECOMPILE_SHA2_BLOCKS to 45u,
+ // Block limits
+ TracingModuleV2.BLOCK_KECCAK to 46u,
+ TracingModuleV2.BLOCK_L1_SIZE to 47u,
+ TracingModuleV2.BLOCK_L2_L1_LOGS to 48u,
+ TracingModuleV2.BLOCK_TRANSACTIONS to 49u
+ )
+)
diff --git a/coordinator/app/src/test/resources/configs/coordinator-traces-v2-override.config.toml b/coordinator/app/src/test/resources/configs/coordinator-traces-v2-override.config.toml
new file mode 100644
index 000000000..c9e01f473
--- /dev/null
+++ b/coordinator/app/src/test/resources/configs/coordinator-traces-v2-override.config.toml
@@ -0,0 +1,40 @@
+[prover]
+[prover.execution]
+fs-requests-directory = "/data/prover/v3/execution/requests"
+fs-responses-directory = "/data/prover/v3/execution/responses"
+[prover.blob-compression]
+fs-requests-directory = "/data/prover/v3/compression/requests"
+fs-responses-directory = "/data/prover/v3/compression/responses"
+[prover.proof-aggregation]
+fs-requests-directory = "/data/prover/v3/aggregation/requests"
+fs-responses-directory = "/data/prover/v3/aggregation/responses"
+
+[zk-traces]
+eth-api="http://traces-node-v2:8545"
+
+[traces]
+switch-to-linea-besu=true
+blob-compressor-version="V1_0_1"
+expected-traces-api-version-v2="v0.8.0-rc8"
+[traces.counters-v2]
+endpoints=["http://traces-node-v2:8545/"]
+request-limit-per-endpoint=1
+request-retry.backoff-delay="PT1S"
+request-retry.failures-warning-threshold=2
+[traces.conflation-v2]
+endpoints=["http://traces-node-v2:8545/"]
+request-limit-per-endpoint=1
+request-retry.backoff-delay="PT1S"
+request-retry.failures-warning-threshold=2
+
+[l2-network-gas-pricing.json-rpc-pricing-propagation]
+geth-gas-price-update-recipients=[
+ "http://l2-node:8545/"
+]
+
+[l2-network-gas-pricing.legacy.sample-transaction-gas-pricing]
+plain-transfer-cost-multiplier=1.0
+# Ratio of 350 / 29400 is based on data from Mainnet. Only 0.3% of transactions are less profitable than this
+# Meaning 99.7% of transactions will be includable if priced using eth_gasPrice
+compressed-tx-size=350
+expected-gas=29400
diff --git a/coordinator/app/src/test/resources/configs/coordinator-web3signer-override.config.toml b/coordinator/app/src/test/resources/configs/coordinator-web3signer-override.config.toml
new file mode 100644
index 000000000..b5fd4ef35
--- /dev/null
+++ b/coordinator/app/src/test/resources/configs/coordinator-web3signer-override.config.toml
@@ -0,0 +1,13 @@
+[finalization-signer]
+# Web3j/Web3signer
+type="Web3Signer"
+
+[data-submission-signer]
+# Web3j/Web3signer
+type="Web3Signer"
+
+[l2-signer]
+# Web3j/Web3signer
+type="Web3Signer"
+
+
diff --git a/coordinator/app/src/test/resources/configs/coordinator.config.toml b/coordinator/app/src/test/resources/configs/coordinator.config.toml
new file mode 100644
index 000000000..62ce6851f
--- /dev/null
+++ b/coordinator/app/src/test/resources/configs/coordinator.config.toml
@@ -0,0 +1,292 @@
+testL1Disabled=false
+
+duplicated-logs-debounce-time="PT15S"
+
+eip4844-switch-l2-block-number=0
+
+[prover]
+fs-inprogress-request-writing-suffix = ".inprogress_coordinator_writing"
+fs-inprogress-proving-suffix-pattern = ".*\\.inprogress\\.prover.*"
+fs-polling-interval = "PT1S"
+fs-polling-timeout = "PT10M"
+[prover.execution]
+fs-requests-directory = "/data/prover/v2/execution/requests"
+fs-responses-directory = "/data/prover/v2/execution/responses"
+[prover.blob-compression]
+fs-requests-directory = "/data/prover/v2/compression/requests"
+fs-responses-directory = "/data/prover/v2/compression/responses"
+[prover.proof-aggregation]
+fs-requests-directory = "/data/prover/v2/aggregation/requests"
+fs-responses-directory = "/data/prover/v2/aggregation/responses"
+#[prover.new]
+#switch-block-number-inclusive=1000
+#[prover.new.execution]
+#fs-requests-directory = "/data/prover/v3/execution/requests"
+#fs-responses-directory = "/data/prover/v3/execution/responses"
+#[prover.new.blob-compression]
+#fs-requests-directory = "/data/prover/v3/compression/requests"
+#fs-responses-directory = "/data/prover/v3/compression/responses"
+#[prover.new.proof-aggregation]
+#fs-requests-directory = "/data/prover/v3/aggregation/requests"
+#fs-responses-directory = "/data/prover/v3/aggregation/responses"
+
+[blob-compression]
+blob-size-limit=102400 # 100KB
+handler-polling-interval="PT1S"
+# default batches limit is aggregation-proofs-limit -1
+# batches-limit must be less than or equal to aggregation-proofs-limit-1
+batches-limit=1
+
+[zk-traces]
+eth-api="http://traces-node:8545"
+new-block-polling-interval="PT1S"
+
+[traces]
+switch-to-linea-besu=false
+blob-compressor-version="V0_1_0"
+raw-execution-traces-version="0.2.0"
+expected-traces-api-version="0.2.0"
+[traces.counters]
+endpoints=["http://traces-api:8080/"]
+request-limit-per-endpoint=2
+request-retry.backoff-delay="PT1S"
+request-retry.failures-warning-threshold=2
+[traces.conflation]
+endpoints=["http://traces-api:8080/"]
+request-limit-per-endpoint=2
+request-retry.backoff-delay="PT1S"
+request-retry.failures-warning-threshold=2
+
+
+[traces.file-manager]
+traces-file-extension="json.gz"
+raw-traces-directory="/data/traces/raw"
+non-canonical-raw-traces-directory="/data/traces/raw-non-canonical"
+create-non-canonical-directory=true
+polling-interval="PT1S"
+traces-file-creation-wait-timeout="PT2M"
+
+[state-manager]
+version="2.3.0"
+endpoints=["http://shomei:8888/"]
+request-limit-per-endpoint=2
+request-retry.backoff-delay="PT2S"
+request-retry.failures-warning-threshold=2
+
+[type2-state-proof-provider]
+endpoints=["http://shomei-frontend:8888/"]
+request-retry.backoff-delay="PT1S"
+request-retry.failures-warning-threshold=2
+
+[api]
+observability_port=9545
+
+[l1]
+rpc-endpoint="http://l1-el-node:8545"
+zk-evm-contract-address="0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9"
+finalization-polling-interval="PT6S"
+l1-query-block-tag="latest"
+gas-limit=10000000
+fee-history-block-count=10
+fee-history-reward-percentile=15
+# Global caps of maxFeePerGas, maxFeePerBlobGas, and maxPriorityFeePerGas
+# for L1 transactions regardless of L1 dynamic gas price cap is enabled or not
+max-fee-per-gas-cap=100000000000
+max-fee-per-blob-gas-cap=100000000000
+max-priority-fee-per-gas-cap=20000000000
+# The multiplier of global caps for L1 finalization transaction
+# E.g. if set as 2.0, it means the global caps of finalization txn
+# will always be 2 times higher than that of blob submission txn
+gas-price-cap-multiplier-for-finalization=2.0
+# blocks are 2s, this may catch in between blocks
+send-message-event-polling-interval="PT1S"
+# 10 blocks worth at 2s per block
+max-event-scraping-time="PT5S"
+# An optional config to define the L1 block time with default as PT12S
+block-time="PT1S" # set the same as local L1 block time
+block-range-loop-limit=500
+max-messages-to-collect=1000
+finalized-block-tag="latest"
+# reset this once we know what to do on dev/UAT
+earliest-block=0
+genesis-state-root-hash="0x072ead6777750dc20232d1cee8dc9a395c2d350df4bbaa5096c6f59b214dcecd"
+# shnarf for contract V5
+# Keccak256(parentShnarf="0x00...00", snarkHash="0x00...00",
+# parentStateRootHash="0x072ead6777750dc20232d1cee8dc9a395c2d350df4bbaa5096c6f59b214dcecd",
+# evaludationClaim="0x00...00", evaludationPoint="0x00...00")
+genesis-shnarf-v5="0x47452a1b9ebadfe02bdd02f580fa1eba17680d57eec968a591644d05d78ee84f"
+
+[l2]
+rpc-endpoint="http://sequencer:8545"
+message-service-address="0xe537D669CA013d86EBeF1D64e40fC74CADC91987"
+gas-limit=10000000
+max-fee-per-gas-cap=100000000000
+fee-history-block-count=4
+fee-history-reward-percentile=15
+last-hash-search-window=25
+anchoring-receipt-polling-interval="PT01S"
+max-receipt-retries=120
+# Number of children blocks to wait before considering a won't be reverted and elegible for conflation.
+# this a workaround to mitigate Geth fork issues with Clique PoA
+# Coordinator will consider block as finalized after being included in the chain wtih children blocks-to-finalization
+# Recommended: Geth sequencer minimum of 2, Besu sequencer minimum of 1, 0 is safe localy
+blocks-to-finalization=0
+
+[blob-submission]
+disabled=true
+db-polling-interval="PT1S"
+max-blobs-to-return=100
+proof-submission-delay="PT1S"
+max-blobs-to-submit-per-tick=10
+# These lower and upper bounds will be effective only if L1 dynamic
+# gas price cap is disabled or during fallback when there's insufficient
+# cached fee history data to compute dynamic gas price caps
+priority-fee-per-gas-upper-bound=2000000000 # 2 GWEI
+priority-fee-per-gas-lower-bound=200000000 # 0.2 GWEI
+
+[aggregation-finalization]
+disabled=false
+db-polling-interval="PT1S"
+max-aggregations-to-finalize-per-tick=1
+proof-submission-delay="PT1S"
+
+[proof-aggregation]
+aggregation-proofs-limit=3
+aggregation-deadline="PT10S"
+aggregation-coordinator-polling-interval="PT2S"
+deadline-check-interval="PT8S"
+target-end-blocks=[]
+
+[finalization-signer]
+# Web3j/Web3signer
+type="Web3j"
+
+[finalization-signer.web3j]
+private-key="0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
+
+[finalization-signer.web3signer]
+endpoint="http://web3signer:9000"
+max-pool-size=10
+keep-alive=true
+public-key="ba5734d8f7091719471e7f7ed6b9df170dc70cc661ca05e688601ad984f068b0d67351e5f06073092499336ab0839ef8a521afd334e53807205fa2f08eec74f4"
+
+[data-submission-signer]
+# Web3j/Web3signer
+type="Web3j"
+
+# The account with this private key is in genesis file
+[data-submission-signer.web3j]
+private-key="0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a"
+
+[data-submission-signer.web3signer]
+endpoint="http://web3signer:9000"
+max-pool-size=10
+keep-alive=true
+public-key="9d9031e97dd78ff8c15aa86939de9b1e791066a0224e331bc962a2099a7b1f0464b8bbafe1535f2301c72c2cb3535b172da30b02686ab0393d348614f157fbdb"
+
+[l2-signer]
+# Web3j/Web3signer
+type="Web3j"
+
+[l2-signer.web3j]
+private-key="0x4d01ae6487860981699236a58b68f807ee5f17b12df5740b85cf4c4653be0f55"
+
+[l2-signer.web3signer]
+endpoint="http://web3signer:9000"
+max-pool-size=10
+keep-alive=true
+public-key="4a788ad6fa008beed58de6418369717d7492f37d173d70e2c26d9737e2c6eeae929452ef8602a19410844db3e200a0e73f5208fd76259a8766b73953fc3e7023"
+
+[message-anchoring-service]
+disabled=false
+polling-interval="PT1S"
+max-messages-to-anchor=100
+
+[l2-network-gas-pricing]
+disabled = false
+price-update-interval = "PT12S"
+
+fee-history-block-count = 50
+fee-history-reward-percentile = 15
+
+blob-submission-expected-execution-gas = 213000.0 # Lower to 120k as we improve efficiency
+# Defaults to expected-blob-gas
+#bytes-per-data-submission=131072.0 # 2^17
+l1-blob-gas = 131072 # 2^17
+
+[l2-network-gas-pricing.request-retry]
+max-retries = 3
+timeout = "PT6S"
+backoff-delay = "PT1S"
+failures-warning-threshold = 2
+
+[l2-network-gas-pricing.variable-cost-pricing]
+gas-price-fixed-cost = 3000000
+legacy-fees-multiplier = 1.2
+margin = 4.0
+variable-cost-upper-bound = 10000000001 # ~10 GWEI
+variable-cost-lower-bound = 90000001 # ~0.09 GWEI
+
+[l2-network-gas-pricing.extra-data-pricing-propagation]
+extra-data-update-recipient = "http://sequencer:8545/"
+
+[l2-network-gas-pricing.legacy]
+type="SampleTransaction"
+gas-price-upper-bound = 10000000000 # 10 GWEI
+gas-price-lower-bound = 90000000 # 0.09 GWEI
+
+[l2-network-gas-pricing.json-rpc-pricing-propagation]
+geth-gas-price-update-recipients = [
+ "http://l2-node:8545/"
+]
+besu-gas-price-update-recipients = []
+
+[l1-dynamic-gas-price-cap-service]
+disabled=false
+[l1-dynamic-gas-price-cap-service.gas-price-cap-calculation]
+adjustment-constant=25
+blob-adjustment-constant=25
+finalization-target-max-delay="PT30S"
+gas-fee-percentile-window="PT1M"
+gas-fee-percentile-window-leeway="PT10S"
+gas-fee-percentile=10
+gas-price-caps-check-coefficient=0.9
+# The lower bound of the "historic base fee per blob gas" used in
+# the L1 dynamic gas price cap equation
+historic-base-fee-per-blob-gas-lower-bound=100000000 # 0.1 GWEI
+# An optional config to replace the "historic average reward" used in
+# the L1 dynamic gas price cap equation
+historic-avg-reward-constant=100000000 # 0.1 GWEI
+[l1-dynamic-gas-price-cap-service.fee-history-fetcher]
+fetch-interval="PT1S"
+max-block-count=1000
+reward-percentiles=[10,20,30,40,50,60,70,80,90,100]
+num-of-blocks-before-latest=4
+[l1-dynamic-gas-price-cap-service.fee-history-storage]
+storage-period="PT2M"
+
+[conflation]
+blocks-limit=2
+conflation-deadline="PT6S" # =3*l2_block_time
+conflation-deadline-check-interval="PT3S"
+conflation-deadline-last-block-confirmation-delay="PT2S" # recommended: at least 2 * blockInterval
+
+# This is to prevent inflight trasactions that may change Smart contract state while coordinator is restarted.
+# Queries SMC for last finalised block, and keeps polling until this number of blocks observe the same state.
+# If state is updated meanwhile, it resets counter and restarts the polling.
+consistent-number-of-blocks-on-l1-to-wait=1
+fetch-blocks-limit=4000
+
+[database]
+host="postgres"
+port="5432"
+username="postgres"
+password="postgres"
+schema="linea_coordinator"
+read_pool_size=10
+read_pipelining_limit=10
+transactional_pool_size=10
+
+[persistence-retry]
+#max-retries = 10 commented as can be null
+backoff-delay = "PT1S"
diff --git a/coordinator/app/src/test/resources/configs/gas-price-cap-time-of-day-multipliers.toml b/coordinator/app/src/test/resources/configs/gas-price-cap-time-of-day-multipliers.toml
new file mode 100644
index 000000000..36155bd6b
--- /dev/null
+++ b/coordinator/app/src/test/resources/configs/gas-price-cap-time-of-day-multipliers.toml
@@ -0,0 +1,184 @@
+##
+# Time of day multipliers for dynamic gas price cap calculation:
+#
+# TDM stands for "Time of Day Mutliplier" and has a range of values between 0.25 - 1.75.
+#
+# When we expect the L1 gas price to be low, for example on a Saturday night, the TDM will be at it's highest because
+# we want to increase the rate at which we increase the threshold to try and settle within this time window.
+# The value will be at it's lowest during peak L1 gas price times, for example, on a Tuesday afternoon, because we
+# know it is likely to be expensive during this window.
+#
+# The values for the TDM based on the 90D of L1 gas price real world data. It is expected that every few months
+# we will update this table with the latest data to account for any notable changes in the trends of L1 gas prices.
+# It does not account for public holidays yet.
+##
+
+[gas-price-cap-time-of-day-multipliers]
+SUNDAY_0 = 1.7489178377946066
+SUNDAY_1 = 1.7494632175198737
+SUNDAY_2 = 1.75
+SUNDAY_3 = 1.733166295438555
+SUNDAY_4 = 1.6993775444542885
+SUNDAY_5 = 1.6350086618091364
+SUNDAY_6 = 1.5627740860151331
+SUNDAY_7 = 1.4831149222064164
+SUNDAY_8 = 1.4101476768256929
+SUNDAY_9 = 1.370085278922007
+SUNDAY_10 = 1.3516015544068651
+SUNDAY_11 = 1.3482404546676368
+SUNDAY_12 = 1.3580905751578942
+SUNDAY_13 = 1.3775497419563296
+SUNDAY_14 = 1.3700255667542938
+SUNDAY_15 = 1.2642948506461285
+SUNDAY_16 = 1.2794806131912935
+SUNDAY_17 = 1.2750892256476676
+SUNDAY_18 = 1.2919720208955585
+SUNDAY_19 = 1.317984990098603
+SUNDAY_20 = 1.4433501639513178
+SUNDAY_21 = 1.4705921238901998
+SUNDAY_22 = 1.515043370430801
+SUNDAY_23 = 1.5556742617266397
+MONDAY_0 = 1.5381562278760164
+MONDAY_1 = 1.5423761828433993
+MONDAY_2 = 1.539015963719092
+MONDAY_3 = 1.487676153648977
+MONDAY_4 = 1.430973985132037
+MONDAY_5 = 1.4656765439056292
+MONDAY_6 = 1.4484298622828233
+MONDAY_7 = 1.4459076216659752
+MONDAY_8 = 1.4899061835032241
+MONDAY_9 = 1.5249733712852067
+MONDAY_10 = 1.511367489481033
+MONDAY_11 = 1.4225695658047797
+MONDAY_12 = 1.2887291896624584
+MONDAY_13 = 1.1460926897291355
+MONDAY_14 = 1.0004897955233254
+MONDAY_15 = 0.8694664537368378
+MONDAY_16 = 0.8270273375962802
+MONDAY_17 = 0.7868289022833883
+MONDAY_18 = 0.7780303121746551
+MONDAY_19 = 0.7756215256634205
+MONDAY_20 = 0.7984895728860915
+MONDAY_21 = 0.8918589268832423
+MONDAY_22 = 0.9967716668541272
+MONDAY_23 = 1.0973334887144106
+TUESDAY_0 = 1.2233064209957951
+TUESDAY_1 = 1.3238883432855082
+TUESDAY_2 = 1.3874518307497257
+TUESDAY_3 = 1.463621147171298
+TUESDAY_4 = 1.4975989065490154
+TUESDAY_5 = 1.481679186141442
+TUESDAY_6 = 1.452778387763161
+TUESDAY_7 = 1.3414858185569951
+TUESDAY_8 = 1.2869454637983988
+TUESDAY_9 = 1.249347290389873
+TUESDAY_10 = 1.196488297386161
+TUESDAY_11 = 1.1136140507034202
+TUESDAY_12 = 0.9867528660797885
+TUESDAY_13 = 0.8018989158195754
+TUESDAY_14 = 0.6173048748109258
+TUESDAY_15 = 0.46718586671750373
+TUESDAY_16 = 0.4103633833041902
+TUESDAY_17 = 0.4871260756989506
+TUESDAY_18 = 0.5667378483016126
+TUESDAY_19 = 0.6464203510900723
+TUESDAY_20 = 0.7780268325299871
+TUESDAY_21 = 0.8995921101255763
+TUESDAY_22 = 1.0077600114996088
+TUESDAY_23 = 1.1109769960680498
+WEDNESDAY_0 = 1.2097668746150059
+WEDNESDAY_1 = 1.2631002319009361
+WEDNESDAY_2 = 1.2912775191940549
+WEDNESDAY_3 = 1.3229785939630059
+WEDNESDAY_4 = 1.3428607301494424
+WEDNESDAY_5 = 1.3750788517823973
+WEDNESDAY_6 = 1.3752344527256497
+WEDNESDAY_7 = 1.3505490078766218
+WEDNESDAY_8 = 1.2598503219367945
+WEDNESDAY_9 = 1.2051668977452374
+WEDNESDAY_10 = 1.0320896222195326
+WEDNESDAY_11 = 0.8900138031631949
+WEDNESDAY_12 = 0.6341155208698448
+WEDNESDAY_13 = 0.48337590254714624
+WEDNESDAY_14 = 0.2903189399226416
+WEDNESDAY_15 = 0.25
+WEDNESDAY_16 = 0.25711039485046006
+WEDNESDAY_17 = 0.37307641907591793
+WEDNESDAY_18 = 0.45280799454961196
+WEDNESDAY_19 = 0.5631397823847637
+WEDNESDAY_20 = 0.6285005244224133
+WEDNESDAY_21 = 0.6671897537279405
+WEDNESDAY_22 = 0.7268406397452634
+WEDNESDAY_23 = 0.8068904097486369
+THURSDAY_0 = 0.9021601102971811
+THURSDAY_1 = 1.023741688964238
+THURSDAY_2 = 1.1340689935096755
+THURSDAY_3 = 1.2530130345819006
+THURSDAY_4 = 1.3163421664973542
+THURSDAY_5 = 1.3536343767230727
+THURSDAY_6 = 1.3432290485306728
+THURSDAY_7 = 1.2864983218982178
+THURSDAY_8 = 1.2320488534113174
+THURSDAY_9 = 1.1984530721079034
+THURSDAY_10 = 1.0877338251341975
+THURSDAY_11 = 0.9999324929016475
+THURSDAY_12 = 0.87536726762619
+THURSDAY_13 = 0.6560822412167919
+THURSDAY_14 = 0.44836474861432074
+THURSDAY_15 = 0.36145134935025247
+THURSDAY_16 = 0.2695997829759713
+THURSDAY_17 = 0.2898426312618241
+THURSDAY_18 = 0.3970093434340387
+THURSDAY_19 = 0.5193273246848977
+THURSDAY_20 = 0.6426415257034419
+THURSDAY_21 = 0.800685718218497
+THURSDAY_22 = 0.9215516833839711
+THURSDAY_23 = 1.053701659160912
+FRIDAY_0 = 1.149649788723893
+FRIDAY_1 = 1.2046315447861193
+FRIDAY_2 = 1.2724031281576726
+FRIDAY_3 = 1.3525693456352732
+FRIDAY_4 = 1.3746126314960814
+FRIDAY_5 = 1.3744591862592468
+FRIDAY_6 = 1.3297812543035683
+FRIDAY_7 = 1.2762064429631657
+FRIDAY_8 = 1.235662409263294
+FRIDAY_9 = 1.2171558028785991
+FRIDAY_10 = 1.182722399785398
+FRIDAY_11 = 1.137345538963285
+FRIDAY_12 = 0.9999308422620752
+FRIDAY_13 = 0.8055000309055653
+FRIDAY_14 = 0.5667135273493851
+FRIDAY_15 = 0.4081529603000651
+FRIDAY_16 = 0.3987031354907009
+FRIDAY_17 = 0.5030075499003412
+FRIDAY_18 = 0.6518159532641841
+FRIDAY_19 = 0.8733483414970974
+FRIDAY_20 = 1.0496224913080463
+FRIDAY_21 = 1.1820684558591705
+FRIDAY_22 = 1.2561688567574458
+FRIDAY_23 = 1.3204704912328773
+SATURDAY_0 = 1.3832230236620218
+SATURDAY_1 = 1.4632908341022142
+SATURDAY_2 = 1.5019230781315296
+SATURDAY_3 = 1.5437332506007084
+SATURDAY_4 = 1.5934153179751855
+SATURDAY_5 = 1.6245578072557723
+SATURDAY_6 = 1.6294919789890665
+SATURDAY_7 = 1.6027665451672717
+SATURDAY_8 = 1.6068061069158674
+SATURDAY_9 = 1.624257927970777
+SATURDAY_10 = 1.5996112411089
+SATURDAY_11 = 1.5659672993092648
+SATURDAY_12 = 1.5333537902522736
+SATURDAY_13 = 1.445292929996356
+SATURDAY_14 = 1.2966021477035259
+SATURDAY_15 = 1.250999408961155
+SATURDAY_16 = 1.2535364828163025
+SATURDAY_17 = 1.2736456128871074
+SATURDAY_18 = 1.3348268054897328
+SATURDAY_19 = 1.4571388900094875
+SATURDAY_20 = 1.5073787902995706
+SATURDAY_21 = 1.5605139580010123
+SATURDAY_22 = 1.5885303316932382
+SATURDAY_23 = 1.6169891066719597
diff --git a/coordinator/app/src/test/resources/configs/smart-contract-errors.toml b/coordinator/app/src/test/resources/configs/smart-contract-errors.toml
new file mode 100644
index 000000000..1de93403e
--- /dev/null
+++ b/coordinator/app/src/test/resources/configs/smart-contract-errors.toml
@@ -0,0 +1,10 @@
+##
+# Smart contract error codes from:
+# https://www.notion.so/consensys/Smart-Contracts-Error-Code-Registry-bb4bd68f8ddf4b0ba90000d1136e42ef
+##
+
+[smart-contract-errors]
+# L1 Linea Rollup
+"0f06cd15" = "DataAlreadySubmitted"
+"c01eab56" = "EmptySubmissionData"
+"abefa5e8" = "DataStartingBlockDoesNotMatch"
diff --git a/coordinator/app/src/test/resources/configs/traces-limits-v1.toml b/coordinator/app/src/test/resources/configs/traces-limits-v1.toml
new file mode 100644
index 000000000..e7c727a80
--- /dev/null
+++ b/coordinator/app/src/test/resources/configs/traces-limits-v1.toml
@@ -0,0 +1,40 @@
+[traces-limits]
+# EVM Arithmetization Limits
+ADD = 1
+BIN = 2
+BIN_RT = 3
+EC_DATA = 4
+EXT = 5
+HUB = 6
+INSTRUCTION_DECODER = 7
+MMIO = 8
+MMU = 9
+MMU_ID = 10
+MOD = 11
+MUL = 12
+MXP = 13
+PHONEY_RLP = 14
+PUB_HASH = 15
+PUB_HASH_INFO = 16
+PUB_LOG = 17
+PUB_LOG_INFO = 18
+RLP = 19
+ROM = 20
+SHF = 21
+SHF_RT = 22
+TX_RLP = 23
+WCP = 24
+# Block Limits
+BLOCK_TX = 25
+BLOCK_L2L1LOGS = 26
+BLOCK_KECCAK = 27
+# Precompile Limits
+PRECOMPILE_ECRECOVER = 28
+PRECOMPILE_SHA2 = 29
+PRECOMPILE_RIPEMD = 30
+PRECOMPILE_IDENTITY = 31
+PRECOMPILE_MODEXP = 32
+PRECOMPILE_ECADD = 32
+PRECOMPILE_ECMUL = 34
+PRECOMPILE_ECPAIRING = 35
+PRECOMPILE_BLAKE2F = 36
diff --git a/coordinator/app/src/test/resources/configs/traces-limits-v2.toml b/coordinator/app/src/test/resources/configs/traces-limits-v2.toml
new file mode 100644
index 000000000..5ece38b4b
--- /dev/null
+++ b/coordinator/app/src/test/resources/configs/traces-limits-v2.toml
@@ -0,0 +1,53 @@
+[traces-limits]
+# Arithmetization module limits
+ADD = 1
+BIN = 2
+BLAKE_MODEXP_DATA = 3
+BLOCK_DATA = 4
+BLOCK_HASH = 5
+EC_DATA = 6
+EUC = 7
+EXP = 8
+EXT = 9
+GAS = 10
+HUB = 11
+LOG_DATA = 12
+LOG_INFO = 13
+MMIO = 14
+MMU = 15
+MOD = 16
+MUL = 18
+MXP = 19
+OOB = 20
+RLP_ADDR = 21
+RLP_TXN = 22
+RLP_TXN_RCPT = 23
+ROM = 24
+ROM_LEX = 25
+SHAKIRA_DATA = 26
+SHF = 27
+STP = 28
+TRM = 29
+TXN_DATA = 30
+WCP = 31
+# Reference table limits, set to UInt.MAX_VALUE
+BIN_REFERENCE_TABLE = 32
+INSTRUCTION_DECODER = 33
+SHF_REFERENCE_TABLE = 34
+# Precompiles limits
+PRECOMPILE_BLAKE_EFFECTIVE_CALLS = 35
+PRECOMPILE_BLAKE_ROUNDS = 36
+PRECOMPILE_ECADD_EFFECTIVE_CALLS = 37
+PRECOMPILE_ECMUL_EFFECTIVE_CALLS = 38
+PRECOMPILE_ECPAIRING_FINAL_EXPONENTIATIONS = 39
+PRECOMPILE_ECPAIRING_G2_MEMBERSHIP_CALLS = 40
+PRECOMPILE_ECPAIRING_MILLER_LOOPS = 41
+PRECOMPILE_ECRECOVER_EFFECTIVE_CALLS = 42
+PRECOMPILE_MODEXP_EFFECTIVE_CALLS = 43
+PRECOMPILE_RIPEMD_BLOCKS = 44
+PRECOMPILE_SHA2_BLOCKS = 45
+# Block limits
+BLOCK_KECCAK = 46
+BLOCK_L1_SIZE = 47
+BLOCK_L2_L1_LOGS = 48
+BLOCK_TRANSACTIONS = 49
From d29cdd4030100339e4f9b4ee45869e3a82e063f6 Mon Sep 17 00:00:00 2001
From: jonesho <81145364+jonesho@users.noreply.github.com>
Date: Wed, 15 Jan 2025 19:13:08 +0800
Subject: [PATCH 6/9] =?UTF-8?q?feat:=20added=20async=20retryer=20for=20cur?=
=?UTF-8?q?rentL2BlockNumber=20in=20case=20the=20contra=E2=80=A6=20(#425)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat: added async retryer for currentL2BlockNumber in case the contract variable is not initialized yet
* feat: revise the use of async retry
* feat: use LineaRollupSmartContractClientReadOnly client for last finalized block
* feat: use LineaRollupSmartContractClientReadOnly client in FinalizationUpdatePoller
* feat: avoid making contract version call during Web3JLineaRollupSmartContractClientReadOnly class init
---
.../zkevm/coordinator/app/L1DependentApp.kt | 24 ++-----
.../app/LastFinalizedBlockProvider.kt | 65 ++++++++-----------
.../L1BasedLastFinalizedBlockProviderTest.kt | 40 +++++-------
.../staticcap/FeeHistoryFetcherImpl.kt | 2 +-
finalized-tag-updater/build.gradle | 2 +-
.../linea/FinalizationUpdatePoller.kt | 49 +++++++-------
.../LineaL1FinalizationUpdaterService.kt | 22 +++----
...JLineaRollupSmartContractClientReadOnly.kt | 7 +-
8 files changed, 87 insertions(+), 124 deletions(-)
diff --git a/coordinator/app/src/main/kotlin/net/consensys/zkevm/coordinator/app/L1DependentApp.kt b/coordinator/app/src/main/kotlin/net/consensys/zkevm/coordinator/app/L1DependentApp.kt
index 9986f7d07..3dff8e2fb 100644
--- a/coordinator/app/src/main/kotlin/net/consensys/zkevm/coordinator/app/L1DependentApp.kt
+++ b/coordinator/app/src/main/kotlin/net/consensys/zkevm/coordinator/app/L1DependentApp.kt
@@ -9,7 +9,6 @@ import kotlinx.datetime.Clock
import linea.encoding.BlockRLPEncoder
import net.consensys.linea.BlockNumberAndHash
import net.consensys.linea.blob.ShnarfCalculatorVersion
-import net.consensys.linea.contract.LineaRollupAsyncFriendly
import net.consensys.linea.contract.Web3JL2MessageService
import net.consensys.linea.contract.Web3JL2MessageServiceLogsClient
import net.consensys.linea.contract.Web3JLogsClient
@@ -220,20 +219,19 @@ class L1DependentApp(
)
)
- private val l1FinalizationMonitor = run {
- // To avoid setDefaultBlockParameter clashes
- val contractClient: LineaRollupSmartContractClientReadOnly = Web3JLineaRollupSmartContractClientReadOnly(
- contractAddress = configs.l1.zkEvmContractAddress,
- web3j = l1Web3jClient
- )
+ private val lineaRollupClient: LineaRollupSmartContractClientReadOnly = Web3JLineaRollupSmartContractClientReadOnly(
+ contractAddress = configs.l1.zkEvmContractAddress,
+ web3j = l1Web3jClient
+ )
+ private val l1FinalizationMonitor = run {
FinalizationMonitorImpl(
config =
FinalizationMonitorImpl.Config(
pollingInterval = configs.l1.finalizationPollingInterval.toKotlinDuration(),
l1QueryBlockTag = configs.l1.l1QueryBlockTag
),
- contract = contractClient,
+ contract = lineaRollupClient,
l2Client = l2Web3jClient,
vertx = vertx
)
@@ -922,17 +920,9 @@ class L1DependentApp(
}
private fun lastFinalizedBlock(): SafeFuture {
- val zkEvmClient: LineaRollupAsyncFriendly = instantiateZkEvmContractClient(
- configs.l1,
- finalizationTransactionManager,
- feesFetcher,
- l1MinPriorityFeeCalculator,
- l1Web3jClient,
- smartContractErrors
- )
val l1BasedLastFinalizedBlockProvider = L1BasedLastFinalizedBlockProvider(
vertx,
- zkEvmClient,
+ lineaRollupClient,
configs.conflation.consistentNumberOfBlocksOnL1ToWait.toUInt()
)
return l1BasedLastFinalizedBlockProvider.getLastFinalizedBlock()
diff --git a/coordinator/app/src/main/kotlin/net/consensys/zkevm/coordinator/app/LastFinalizedBlockProvider.kt b/coordinator/app/src/main/kotlin/net/consensys/zkevm/coordinator/app/LastFinalizedBlockProvider.kt
index 74987b5d9..cefdeff19 100644
--- a/coordinator/app/src/main/kotlin/net/consensys/zkevm/coordinator/app/LastFinalizedBlockProvider.kt
+++ b/coordinator/app/src/main/kotlin/net/consensys/zkevm/coordinator/app/LastFinalizedBlockProvider.kt
@@ -1,14 +1,12 @@
package net.consensys.zkevm.coordinator.app
-import build.linea.contract.LineaRollupV5
+import build.linea.contract.l1.LineaRollupSmartContractClientReadOnly
import io.vertx.core.Vertx
+import net.consensys.linea.BlockParameter
import net.consensys.linea.async.AsyncRetryer
-import net.consensys.toULong
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
-import org.web3j.protocol.core.DefaultBlockParameterName
import tech.pegasys.teku.infrastructure.async.SafeFuture
-import java.math.BigInteger
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.atomic.AtomicReference
import kotlin.time.Duration
@@ -26,7 +24,7 @@ interface LastFinalizedBlockProvider {
*/
class L1BasedLastFinalizedBlockProvider(
private val vertx: Vertx,
- private val lineaRollupSmartContractWeb3jClient: LineaRollupV5,
+ private val lineaRollupSmartContractClient: LineaRollupSmartContractClientReadOnly,
private val consistentNumberOfBlocksOnL1: UInt,
private val numberOfRetries: UInt = Int.MAX_VALUE.toUInt(),
private val pollingInterval: Duration = 2.seconds
@@ -34,42 +32,33 @@ class L1BasedLastFinalizedBlockProvider(
private val log: Logger = LogManager.getLogger(this::class.java)
override fun getLastFinalizedBlock(): SafeFuture {
- lineaRollupSmartContractWeb3jClient.setDefaultBlockParameter(DefaultBlockParameterName.LATEST)
-
- return SafeFuture.of(lineaRollupSmartContractWeb3jClient.currentL2BlockNumber().sendAsync())
- .thenCompose { blockNumber ->
+ val lastObservedBlock = AtomicReference(null)
+ val numberOfObservations = AtomicInteger(1)
+ val isConsistentEnough = { lastPolledBlockNumber: ULong ->
+ if (lastPolledBlockNumber == lastObservedBlock.get()) {
+ numberOfObservations.incrementAndGet().toUInt() >= consistentNumberOfBlocksOnL1
+ } else {
log.info(
- "Rollup lastFinalizedBlockNumber={} waiting {} blocks for confirmation for no updates",
- blockNumber,
+ "Rollup finalized block updated from {} to {}, waiting {} blocks for confirmation",
+ lastObservedBlock.get(),
+ lastPolledBlockNumber,
consistentNumberOfBlocksOnL1
)
- val lastObservedBlock = AtomicReference(blockNumber)
- val numberOfObservations = AtomicInteger(1)
- val isConsistentEnough = { lasPolledBlockNumber: BigInteger ->
- if (lasPolledBlockNumber == lastObservedBlock.get()) {
- numberOfObservations.incrementAndGet().toUInt() >= consistentNumberOfBlocksOnL1
- } else {
- log.info(
- "Rollup finalized block updated from {} to {}, waiting {} blocks for confirmation",
- blockNumber,
- lasPolledBlockNumber,
- consistentNumberOfBlocksOnL1
- )
- numberOfObservations.set(1)
- lastObservedBlock.set(lasPolledBlockNumber)
- false
- }
- }
-
- AsyncRetryer.retry(
- vertx,
- maxRetries = numberOfRetries.toInt(),
- backoffDelay = pollingInterval,
- stopRetriesPredicate = isConsistentEnough
- ) {
- SafeFuture.of(lineaRollupSmartContractWeb3jClient.currentL2BlockNumber().sendAsync())
- }
+ numberOfObservations.set(1)
+ lastObservedBlock.set(lastPolledBlockNumber)
+ false
}
- .thenApply { it.toULong() }
+ }
+
+ return AsyncRetryer.retry(
+ vertx,
+ maxRetries = numberOfRetries.toInt(),
+ backoffDelay = pollingInterval,
+ stopRetriesPredicate = isConsistentEnough
+ ) {
+ lineaRollupSmartContractClient.finalizedL2BlockNumber(
+ blockParameter = BlockParameter.Tag.LATEST
+ )
+ }
}
}
diff --git a/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/L1BasedLastFinalizedBlockProviderTest.kt b/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/L1BasedLastFinalizedBlockProviderTest.kt
index 6632e7e3a..e9a655e99 100644
--- a/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/L1BasedLastFinalizedBlockProviderTest.kt
+++ b/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/L1BasedLastFinalizedBlockProviderTest.kt
@@ -1,42 +1,39 @@
package net.consensys.zkevm.coordinator.app
-import build.linea.contract.LineaRollupV5
+import build.linea.contract.l1.LineaRollupSmartContractClientReadOnly
import io.vertx.core.Vertx
+import net.consensys.linea.BlockParameter
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
-import org.mockito.kotlin.doReturn
+import org.mockito.Mockito
+import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
-import org.web3j.protocol.core.RemoteFunctionCall
-import java.math.BigInteger
-import java.util.concurrent.CompletableFuture
+import tech.pegasys.teku.infrastructure.async.SafeFuture
import kotlin.time.Duration.Companion.milliseconds
class L1BasedLastFinalizedBlockProviderTest {
- private lateinit var lineaRollupSmartContractWeb3jClient: LineaRollupV5
+ private lateinit var lineaRollupClient: LineaRollupSmartContractClientReadOnly
@BeforeEach
fun beforeEach() {
- lineaRollupSmartContractWeb3jClient = mock()
+ lineaRollupClient =
+ mock(defaultAnswer = Mockito.RETURNS_DEEP_STUBS)
}
@Test
fun `shall wait number of blocks before returning for consistency`() {
- val replies = listOf(
- mockRemoteFnCallWithBlockNumber(100),
- mockRemoteFnCallWithBlockNumber(100),
- mockRemoteFnCallWithBlockNumber(101),
- mockRemoteFnCallWithBlockNumber(101),
- mockRemoteFnCallWithBlockNumber(101),
- mockRemoteFnCallWithBlockNumber(101)
- )
- whenever(lineaRollupSmartContractWeb3jClient.currentL2BlockNumber())
- .thenReturn(replies[0], *replies.subList(1, replies.size).toTypedArray())
+ val replies = listOf(100UL, 100UL, 101UL, 101UL, 101UL, 101UL)
+ whenever(lineaRollupClient.finalizedL2BlockNumber(eq(BlockParameter.Tag.LATEST)))
+ .thenReturn(
+ SafeFuture.completedFuture(replies[0]),
+ *replies.subList(1, replies.size).map { SafeFuture.completedFuture(it) }.toTypedArray()
+ )
val resumerCalculator = L1BasedLastFinalizedBlockProvider(
Vertx.vertx(),
- lineaRollupSmartContractWeb3jClient,
+ lineaRollupClient,
consistentNumberOfBlocksOnL1 = 3u,
numberOfRetries = 50u,
pollingInterval = 10.milliseconds
@@ -44,11 +41,4 @@ class L1BasedLastFinalizedBlockProviderTest {
assertThat(resumerCalculator.getLastFinalizedBlock().get()).isEqualTo(101.toULong())
}
-
- private fun mockRemoteFnCallWithBlockNumber(blockNumber: Long): RemoteFunctionCall {
- return mock>() {
- on { send() } doReturn (BigInteger.valueOf(blockNumber))
- on { sendAsync() } doReturn (CompletableFuture.completedFuture(BigInteger.valueOf(blockNumber)))
- }
- }
}
diff --git a/coordinator/ethereum/gas-pricing/static-cap/src/main/kotlin/net/consensys/linea/ethereum/gaspricing/staticcap/FeeHistoryFetcherImpl.kt b/coordinator/ethereum/gas-pricing/static-cap/src/main/kotlin/net/consensys/linea/ethereum/gaspricing/staticcap/FeeHistoryFetcherImpl.kt
index a2ee341a2..147fc03d8 100644
--- a/coordinator/ethereum/gas-pricing/static-cap/src/main/kotlin/net/consensys/linea/ethereum/gaspricing/staticcap/FeeHistoryFetcherImpl.kt
+++ b/coordinator/ethereum/gas-pricing/static-cap/src/main/kotlin/net/consensys/linea/ethereum/gaspricing/staticcap/FeeHistoryFetcherImpl.kt
@@ -31,7 +31,7 @@ class FeeHistoryFetcherImpl(
}
private var cacheIsValidForBlockNumber: BigInteger = BigInteger.ZERO
- private var feesCache: FeeHistory = getRecentFees().get()
+ private lateinit var feesCache: FeeHistory
private fun getRecentFees(): SafeFuture {
val blockNumberFuture = web3jClient.ethBlockNumber().sendAsync()
diff --git a/finalized-tag-updater/build.gradle b/finalized-tag-updater/build.gradle
index 93f922a19..ad44e7f66 100644
--- a/finalized-tag-updater/build.gradle
+++ b/finalized-tag-updater/build.gradle
@@ -40,7 +40,7 @@ dependencies {
implementation project(':jvm-libs:linea:core:long-running-service')
implementation project(':jvm-libs:generic:extensions:futures')
implementation project(':jvm-libs:linea:web3j-extensions')
- implementation 'build.linea:l1-rollup-contract-client:6.0.0-rc2'
+ implementation project(':jvm-libs:linea:clients:linea-l1-contract-client')
implementation ("org.web3j:core:${libs.versions.web3j.get()}") {
exclude group: 'org.slf4j', module: 'slf4j-nop'
}
diff --git a/finalized-tag-updater/src/main/kotlin/net/consensys/linea/FinalizationUpdatePoller.kt b/finalized-tag-updater/src/main/kotlin/net/consensys/linea/FinalizationUpdatePoller.kt
index c67889061..57cffeca6 100644
--- a/finalized-tag-updater/src/main/kotlin/net/consensys/linea/FinalizationUpdatePoller.kt
+++ b/finalized-tag-updater/src/main/kotlin/net/consensys/linea/FinalizationUpdatePoller.kt
@@ -1,14 +1,13 @@
package net.consensys.zkevm.ethereum.finalization
-import build.linea.contract.LineaRollupV5
+import build.linea.contract.l1.Web3JLineaRollupSmartContractClientReadOnly
import io.vertx.core.Vertx
+import net.consensys.linea.BlockParameter
+import net.consensys.linea.async.AsyncRetryer
import net.consensys.linea.async.toSafeFuture
-import net.consensys.toULong
import net.consensys.zkevm.PeriodicPollingService
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
-import org.web3j.protocol.core.DefaultBlockParameter
-import org.web3j.protocol.core.DefaultBlockParameterName
import tech.pegasys.teku.infrastructure.async.SafeFuture
import java.util.concurrent.CompletableFuture
import java.util.concurrent.atomic.AtomicReference
@@ -17,24 +16,19 @@ import kotlin.time.Duration.Companion.seconds
data class FinalizationUpdatePollerConfig(
val pollingInterval: Duration = 12.seconds,
- val blockTag: String
+ val blockTag: BlockParameter
) {
init {
require(pollingInterval >= 0.seconds) {
"pollingInterval must be greater than 0"
}
-
- require(DefaultBlockParameterName.fromString(blockTag) != null) {
- "Invalid blockTag='$blockTag', " +
- "valid values: ${DefaultBlockParameterName.values().joinToString(", ")}"
- }
}
}
class FinalizationUpdatePoller(
- vertx: Vertx,
- config: FinalizationUpdatePollerConfig,
- private val lineaRollup: LineaRollupV5,
+ private val vertx: Vertx,
+ private val config: FinalizationUpdatePollerConfig,
+ private val lineaRollup: Web3JLineaRollupSmartContractClientReadOnly,
private val finalizationHandler: (ULong) -> CompletableFuture<*>,
private val log: Logger = LogManager.getLogger(FinalizationUpdatePoller::class.java)
) : PeriodicPollingService(
@@ -44,22 +38,23 @@ class FinalizationUpdatePoller(
) {
private val lastFinalizationRef: AtomicReference = AtomicReference(null)
- init {
- lineaRollup.setDefaultBlockParameter(DefaultBlockParameter.valueOf(config.blockTag))
- }
-
override fun action(): SafeFuture<*> {
- return lineaRollup.currentL2BlockNumber().sendAsync()
- .thenCompose { lineaFinalizedBlockNumber ->
- val prevFinalizedBlockNumber = lastFinalizationRef.get()
- lastFinalizationRef.set(lineaFinalizedBlockNumber.toULong())
- if (prevFinalizedBlockNumber != lineaFinalizedBlockNumber.toULong()) {
- finalizationHandler(lineaFinalizedBlockNumber.toULong()).thenApply { Unit }
- } else {
- CompletableFuture.completedFuture(Unit)
+ return AsyncRetryer.retry(
+ vertx,
+ backoffDelay = config.pollingInterval
+ ) {
+ lineaRollup.finalizedL2BlockNumber(config.blockTag)
+ .thenCompose { lineaFinalizedBlockNumber ->
+ val prevFinalizedBlockNumber = lastFinalizationRef.get()
+ lastFinalizationRef.set(lineaFinalizedBlockNumber.toULong())
+ if (prevFinalizedBlockNumber != lineaFinalizedBlockNumber.toULong()) {
+ finalizationHandler(lineaFinalizedBlockNumber.toULong()).thenApply { Unit }
+ } else {
+ CompletableFuture.completedFuture(Unit)
+ }
}
- }
- .toSafeFuture()
+ .toSafeFuture()
+ }
}
override fun handleError(error: Throwable) {
diff --git a/finalized-tag-updater/src/main/kotlin/net/consensys/linea/LineaL1FinalizationUpdaterService.kt b/finalized-tag-updater/src/main/kotlin/net/consensys/linea/LineaL1FinalizationUpdaterService.kt
index a1585ea9a..75674a236 100644
--- a/finalized-tag-updater/src/main/kotlin/net/consensys/linea/LineaL1FinalizationUpdaterService.kt
+++ b/finalized-tag-updater/src/main/kotlin/net/consensys/linea/LineaL1FinalizationUpdaterService.kt
@@ -1,6 +1,6 @@
package net.consensys.linea
-import build.linea.contract.LineaRollupV5
+import build.linea.contract.l1.Web3JLineaRollupSmartContractClientReadOnly
import io.vertx.core.Vertx
import net.consensys.linea.consensus.EngineBlockTagUpdater
import net.consensys.linea.web3j.okHttpClientBuilder
@@ -8,15 +8,11 @@ import net.consensys.zkevm.LongRunningService
import net.consensys.zkevm.ethereum.finalization.FinalizationUpdatePoller
import net.consensys.zkevm.ethereum.finalization.FinalizationUpdatePollerConfig
import org.apache.logging.log4j.LogManager
-import org.apache.tuweni.bytes.Bytes
import org.hyperledger.besu.plugin.services.BlockchainService
import org.slf4j.Logger
import org.slf4j.LoggerFactory
-import org.web3j.crypto.Credentials
import org.web3j.protocol.Web3j
import org.web3j.protocol.http.HttpService
-import org.web3j.tx.gas.StaticGasProvider
-import java.math.BigInteger
import java.util.concurrent.CompletableFuture
class LineaBesuEngineBlockTagUpdater(private val blockchainService: BlockchainService) : EngineBlockTagUpdater {
@@ -27,7 +23,11 @@ class LineaBesuEngineBlockTagUpdater(private val blockchainService: BlockchainSe
if (!finalizedBlock.isEmpty) {
try {
val blockHash = finalizedBlock.get().blockHeader.blockHash
- log.info("Linea safe/finalized block update: blockNumber={} blockHash={}", finalizedBlockNumber, blockHash)
+ log.info(
+ "Linea safe/finalized block update: blockNumber={} blockHash={}",
+ finalizedBlockNumber,
+ blockHash
+ )
blockchainService.setSafeBlock(blockHash)
blockchainService.setFinalizedBlock(blockHash)
return true
@@ -86,18 +86,16 @@ class LineaL1FinalizationUpdaterService(
okHttpClientBuilder(LogManager.getLogger("clients.l1")).build()
)
)
- private val lineaRollup = LineaRollupV5.load(
- config.l1SmartContractAddress.toHexString(),
- web3j,
- Credentials.create(Bytes.random(64).toHexString()),
- StaticGasProvider(BigInteger.valueOf(50000000000L), BigInteger.valueOf(60000000L))
+ private val lineaRollup = Web3JLineaRollupSmartContractClientReadOnly(
+ contractAddress = config.l1SmartContractAddress.toHexString(),
+ web3j = web3j
)
private val updater = LineaL1FinalizationUpdater(engineBlockTagUpdater)
private val poller = FinalizationUpdatePoller(
vertx,
FinalizationUpdatePollerConfig(
pollingInterval = config.l1PollingInterval,
- blockTag = "finalized"
+ blockTag = BlockParameter.Tag.FINALIZED
),
lineaRollup,
updater::handleL1Finalization,
diff --git a/jvm-libs/linea/clients/linea-l1-contract-client/src/main/kotlin/build/linea/contract/l1/Web3JLineaRollupSmartContractClientReadOnly.kt b/jvm-libs/linea/clients/linea-l1-contract-client/src/main/kotlin/build/linea/contract/l1/Web3JLineaRollupSmartContractClientReadOnly.kt
index 0d74736ef..34c05faef 100644
--- a/jvm-libs/linea/clients/linea-l1-contract-client/src/main/kotlin/build/linea/contract/l1/Web3JLineaRollupSmartContractClientReadOnly.kt
+++ b/jvm-libs/linea/clients/linea-l1-contract-client/src/main/kotlin/build/linea/contract/l1/Web3JLineaRollupSmartContractClientReadOnly.kt
@@ -63,8 +63,7 @@ open class Web3JLineaRollupSmartContractClientReadOnly(
} as T
}
- protected val smartContractVersionCache: AtomicReference =
- AtomicReference(fetchSmartContractVersion().get())
+ private val smartContractVersionCache = AtomicReference(null)
private fun getSmartContractVersion(): SafeFuture {
return if (smartContractVersionCache.get() == LineaContractVersion.V6) {
@@ -73,7 +72,9 @@ open class Web3JLineaRollupSmartContractClientReadOnly(
} else {
fetchSmartContractVersion()
.thenPeek { contractLatestVersion ->
- if (contractLatestVersion != smartContractVersionCache.get()) {
+ if (smartContractVersionCache.get() != null &&
+ contractLatestVersion != smartContractVersionCache.get()
+ ) {
log.info(
"Smart contract upgraded: prevVersion={} upgradedVersion={}",
smartContractVersionCache.get(),
From fe967c703b9e5f43098a4961dd4c2e6d5e3e5480 Mon Sep 17 00:00:00 2001
From: Pedro Novais <1478752+jpnovais@users.noreply.github.com>
Date: Thu, 16 Jan 2025 10:16:39 +0000
Subject: [PATCH 7/9] State recover part 4 (#324)
* statereover: adds working StateRecoverApp, besu-plugin and Integration tests
---------
Signed-off-by: Pedro Novais <1478752+jpnovais@users.noreply.github.com>
Co-authored-by: jonesho <81145364+jonesho@users.noreply.github.com>
---
Makefile | 22 +-
build.gradle | 5 +-
.../coordinator-docker.config.toml | 10 +-
.../zkevm/coordinator/app/L1DependentApp.kt | 2 +-
.../coordinator/app/SwitchProviderImplTest.kt | 2 +-
.../FileBasedExecutionProverClientV2.kt | 2 +-
.../smart-contract-client/build.gradle | 3 +-
.../contract/Web3JContractAsyncHelper.kt | 6 +-
.../Web3JL2MessageServiceLogsClient.kt | 1 +
.../BlobAndAggregationFinalizationIntTest.kt | 3 +-
.../ethereum/submission/SwitchProviderImpl.kt | 2 +-
.../zkevm/ethereum/AccountManager.kt | 2 +-
docker/compose.yml | 102 ++++
docker/config/linea-local-dev-genesis.json | 147 ------
docker/config/shomei/log4j.xml | 2 +-
docker/config/traces-node-v2/log4j.xml | 2 +-
.../traces-node-v2/traces-node-v2-config.toml | 2 +-
.../zkbesu-shomei/log4j-staterecovery.xml | 53 ++
docker/config/zkbesu-shomei/log4j.xml | 2 +-
docker/linea-sepolia/genesis.json | 4 +-
docker/scripts/file-downloader.sh | 25 -
gradle/libs.versions.toml | 4 +-
.../kotlin/net/consensys/TypingsExtensions.kt | 10 +
.../linea/jsonrpc/TestingJsonRpcServer.kt | 2 +-
.../kotlin/linea/logging/TimeMeasureLogger.kt | 38 ++
.../logging/JsonRpcRequestResponseLogger.kt | 35 +-
.../logging/MinimalInLineJsonRpcLoggerTest.kt | 7 +-
.../s11n/jackson/InstantAsHexNumberSerDe.kt | 21 +
.../linea/s11n/jackson/InstantISO8601SerDe.kt | 1 -
.../jackson/InstantAsHexNumberSerDeTest.kt | 56 +++
jvm-libs/linea/besu-libs/build.gradle | 24 +-
.../linea/besu-rlp-and-mappers/build.gradle | 3 +
jvm-libs/linea/blob-compressor/build.gradle | 4 +
.../main/kotlin/linea/blob/BlobCompressor.kt | 6 +
.../linea/blob/GoBackedBlobCompressorTest.kt | 12 +-
...iveCompressorAndShnarfCalculatorIntTest.kt | 10 +-
.../nativecompressor/CompressorTestData.kt | 32 +-
.../TestDataGeneratorHelper.kt | 70 +++
.../src/testFixtures/resources/blocks_rlp.bin | Bin 0 -> 42062 bytes
.../src/testFixtures/resources/rlp_blocks.bin | Bin 57530 -> 0 bytes
.../blob/GoNativeBlobDecompressorTest.kt | 2 +-
.../src/main/kotlin/linea/EthLogsSearcher.kt | 32 ++
.../main/kotlin/linea/domain/RetryConfig.kt | 32 ++
.../kotlin/linea/domain/RetryConfigTest.kt | 58 +++
.../linea/testing/filesystem/Files.kt | 2 +-
jvm-libs/linea/web3j-extensions/build.gradle | 8 +-
.../build/linea/web3j}/Web3JLogsClient.kt | 2 +-
.../main/kotlin/linea/web3j/SearchCursor.kt | 87 ++++
.../kotlin/linea/web3j/Web3JLogsSearcher.kt | 209 ++++++++
.../linea/web3j}/Web3JLogsClientIntTest.kt | 2 +-
.../build/linea/web3j}/Web3JLogsClientTest.kt | 2 +-
.../kotlin/linea/web3j/SearchCursorTest.kt | 191 +++++++
.../linea/web3j/ULongRangesHelperTest.kt | 117 +++++
.../linea/web3j/Web3JLogsSearcherIntTest.kt | 472 ++++++++++++++++++
.../src/test}/resources/log4j2.xml | 8 +-
settings.gradle | 6 +-
.../appcore/clients-interfaces/build.gradle | 1 +
.../clients/ExecutionLayerClient.kt | 12 -
.../staterecover}/BlobFetcher.kt | 2 +-
.../staterecover/ExecutionLayerClient.kt | 16 +
.../staterecover/RecoveryStatusPersistence.kt | 81 +++
.../staterecover/TransactionDetailsClient.kt | 7 +
.../FileRecoveryStatusPersistenceTest.kt | 87 ++++
.../TransactionL1RecoveredData.kt | 74 ---
.../staterecover/BlockFromL1RecoveredData.kt} | 71 ++-
.../TransactionFromL1RecoveredData.kt | 103 ++++
state-recover/appcore/logic/build.gradle | 27 +
.../BlobDecompressorAndDeserializer.kt | 144 ++++++
.../linea/staterecover/BlockImporter.kt | 77 +++
.../LineaSubmissionEventsClient.kt | 6 +-
.../LineaSubmissionEventsClientImpl.kt} | 157 +++---
.../linea/staterecover/StateRecoverApp.kt | 192 +++++++
.../staterecover/StateSynchronizerService.kt | 163 ++++++
.../BlobDecompressorAndDeserializerV1Test.kt | 137 +++++
state-recover/besu-plugin/build.gradle | 71 +++
.../clients/ExecutionLayerInProcessClient.kt | 110 ++++
.../staterecover/plugin/AppConfigurator.kt | 93 ++++
.../staterecover/plugin/BlockContextData.kt | 13 +
.../staterecover/plugin/BlockImporter.kt | 122 +++++
.../plugin/LineaStateRecoverPlugin.kt | 127 +++++
.../staterecover/plugin/PluginOptions.kt | 107 ++++
.../plugin/RecoveryModeManager.kt | 103 ++++
.../staterecover/plugin/TransactionMapper.kt | 75 +++
.../org.hyperledger.besu.plugin.BesuPlugin | 1 +
.../clients/blobscan-client/build.gradle | 2 +-
.../clients/blobscan/BlobScanClient.kt | 12 +-
.../clients/blobscan/VertxRestClient.kt | 54 +-
.../clients/blobscan/BlobScanClientTest.kt | 2 +-
state-recover/clients/eth-api/build.gradle | 11 +
.../clients/VertxTransactionDetailsClient.kt | 50 ++
.../clients/el/ExecutionLayerJsonRpcClient.kt | 62 ++-
.../el/ExecutionLayerJsonRpcClientTest.kt | 153 +++++-
state-recover/test-cases/build.gradle | 82 +++
.../LineaSubmissionEventsClientIntTest.kt | 30 +-
.../staterecover/StateRecoverAppIntTest.kt | 207 ++++++++
...ecoverAppWithFakeExecutionClientIntTest.kt | 298 +++++++++++
...RecoveryManualReplayToLocalStackIntTest.kt | 152 ++++++
.../src/integrationTest/resources/log4j2.xml | 30 ++
.../test/FakeExecutionLayerClient.kt | 73 +++
...keStateManagerClientBasedOnBlobsRecords.kt | 91 ++++
...erSepoliaWithFakeExecutionClientIntTest.kt | 173 +++++++
.../src/test/resources/vertx-options.json | 15 +
...e872c798b03287eb-getZkAggregatedProof.json | 1 +
...4efd1ec39e60dee1-getZkAggregatedProof.json | 1 +
...b0ed37bf8560eb30-getZkAggregatedProof.json | 1 +
...018ba10e05f52759-getZkAggregatedProof.json | 1 +
...69a1f0981e66fb78-getZkAggregatedProof.json | 1 +
...69175cc9976f4fa4-getZkAggregatedProof.json | 1 +
...41b2e59ca659669a-getZkAggregatedProof.json | 1 +
...df3d6da896186a1e-getZkAggregatedProof.json | 1 +
...bfb166d316bd4825-getZkAggregatedProof.json | 1 +
...759ffca6bd3fed3c-getZkAggregatedProof.json | 1 +
...b9cf5bc245e8982c-getZkAggregatedProof.json | 1 +
...d7ecf32710e3be87-getZkAggregatedProof.json | 1 +
...d6f19734f5e0c88c-getZkAggregatedProof.json | 1 +
...b63279b2ba7f0f2c-getZkAggregatedProof.json | 1 +
...97356d8baedc3e65-getZkAggregatedProof.json | 1 +
...ca536dedd6d4e2ba-getZkAggregatedProof.json | 1 +
...1c8a3f7d977-getZkBlobCompressionProof.json | 1 +
...11f7aefd9e7-getZkBlobCompressionProof.json | 1 +
...945eff7044c-getZkBlobCompressionProof.json | 1 +
...40c8f48b837-getZkBlobCompressionProof.json | 1 +
...7d3a32358c7-getZkBlobCompressionProof.json | 1 +
...f2f3f6bbe5b-getZkBlobCompressionProof.json | 1 +
...3bd9afc921d-getZkBlobCompressionProof.json | 1 +
...e50dddd3f8c-getZkBlobCompressionProof.json | 1 +
...914f2246831-getZkBlobCompressionProof.json | 1 +
...e151d4e2ee8-getZkBlobCompressionProof.json | 1 +
...c5ce4210446-getZkBlobCompressionProof.json | 1 +
...4c83a91b025-getZkBlobCompressionProof.json | 1 +
...4941cf04695-getZkBlobCompressionProof.json | 1 +
...df7e88387da-getZkBlobCompressionProof.json | 1 +
...83f6f2b8061-getZkBlobCompressionProof.json | 1 +
...eea9a7d39cb-getZkBlobCompressionProof.json | 1 +
...f758482aed7-getZkBlobCompressionProof.json | 1 +
135 files changed, 5124 insertions(+), 549 deletions(-)
delete mode 100644 docker/config/linea-local-dev-genesis.json
create mode 100644 docker/config/zkbesu-shomei/log4j-staterecovery.xml
delete mode 100644 docker/scripts/file-downloader.sh
create mode 100644 jvm-libs/generic/logging/src/main/kotlin/linea/logging/TimeMeasureLogger.kt
create mode 100644 jvm-libs/generic/serialization/jackson/src/main/kotlin/build/linea/s11n/jackson/InstantAsHexNumberSerDe.kt
create mode 100644 jvm-libs/generic/serialization/jackson/src/test/kotlin/build/linea/s11n/jackson/InstantAsHexNumberSerDeTest.kt
create mode 100644 jvm-libs/linea/blob-compressor/src/testFixtures/kotlin/net/consensys/linea/nativecompressor/TestDataGeneratorHelper.kt
create mode 100644 jvm-libs/linea/blob-compressor/src/testFixtures/resources/blocks_rlp.bin
delete mode 100644 jvm-libs/linea/blob-compressor/src/testFixtures/resources/rlp_blocks.bin
create mode 100644 jvm-libs/linea/clients/interfaces/src/main/kotlin/linea/EthLogsSearcher.kt
create mode 100644 jvm-libs/linea/core/domain-models/src/main/kotlin/linea/domain/RetryConfig.kt
create mode 100644 jvm-libs/linea/core/domain-models/src/test/kotlin/linea/domain/RetryConfigTest.kt
rename {coordinator/clients/smart-contract-client/src/main/kotlin/net/consensys/linea/contract => jvm-libs/linea/web3j-extensions/src/main/kotlin/build/linea/web3j}/Web3JLogsClient.kt (98%)
create mode 100644 jvm-libs/linea/web3j-extensions/src/main/kotlin/linea/web3j/SearchCursor.kt
create mode 100644 jvm-libs/linea/web3j-extensions/src/main/kotlin/linea/web3j/Web3JLogsSearcher.kt
rename {coordinator/clients/smart-contract-client/src/test/kotlin/net/consensys/linea/contract => jvm-libs/linea/web3j-extensions/src/test/kotlin/build/linea/web3j}/Web3JLogsClientIntTest.kt (99%)
rename {coordinator/clients/smart-contract-client/src/test/kotlin/net/consensys/linea/contract => jvm-libs/linea/web3j-extensions/src/test/kotlin/build/linea/web3j}/Web3JLogsClientTest.kt (99%)
create mode 100644 jvm-libs/linea/web3j-extensions/src/test/kotlin/linea/web3j/SearchCursorTest.kt
create mode 100644 jvm-libs/linea/web3j-extensions/src/test/kotlin/linea/web3j/ULongRangesHelperTest.kt
create mode 100644 jvm-libs/linea/web3j-extensions/src/test/kotlin/linea/web3j/Web3JLogsSearcherIntTest.kt
rename {state-recover/clients/smartcontract/src/integrationTest => jvm-libs/linea/web3j-extensions/src/test}/resources/log4j2.xml (64%)
delete mode 100644 state-recover/appcore/clients-interfaces/src/main/kotlin/build/linea/staterecover/clients/ExecutionLayerClient.kt
rename state-recover/appcore/clients-interfaces/src/main/kotlin/{build/linea/staterecover/clients => linea/staterecover}/BlobFetcher.kt (81%)
create mode 100644 state-recover/appcore/clients-interfaces/src/main/kotlin/linea/staterecover/ExecutionLayerClient.kt
create mode 100644 state-recover/appcore/clients-interfaces/src/main/kotlin/linea/staterecover/RecoveryStatusPersistence.kt
create mode 100644 state-recover/appcore/clients-interfaces/src/main/kotlin/linea/staterecover/TransactionDetailsClient.kt
create mode 100644 state-recover/appcore/clients-interfaces/src/test/kotlin/linea/staterecover/FileRecoveryStatusPersistenceTest.kt
delete mode 100644 state-recover/appcore/domain-models/src/main/kotlin/build/linea/staterecover/TransactionL1RecoveredData.kt
rename state-recover/appcore/domain-models/src/main/kotlin/{build/linea/staterecover/BlockL1RecoveredData.kt => linea/staterecover/BlockFromL1RecoveredData.kt} (68%)
create mode 100644 state-recover/appcore/domain-models/src/main/kotlin/linea/staterecover/TransactionFromL1RecoveredData.kt
create mode 100644 state-recover/appcore/logic/build.gradle
create mode 100644 state-recover/appcore/logic/src/main/kotlin/linea/staterecover/BlobDecompressorAndDeserializer.kt
create mode 100644 state-recover/appcore/logic/src/main/kotlin/linea/staterecover/BlockImporter.kt
rename state-recover/appcore/{clients-interfaces/src/main/kotlin/build/linea/staterecover/clients => logic/src/main/kotlin/linea/staterecover}/LineaSubmissionEventsClient.kt (94%)
rename state-recover/{clients/smartcontract/src/main/kotlin/linea/build/staterecover/clients/smartcontract/LineaSubmissionEventsClientWeb3jIpml.kt => appcore/logic/src/main/kotlin/linea/staterecover/LineaSubmissionEventsClientImpl.kt} (54%)
create mode 100644 state-recover/appcore/logic/src/main/kotlin/linea/staterecover/StateRecoverApp.kt
create mode 100644 state-recover/appcore/logic/src/main/kotlin/linea/staterecover/StateSynchronizerService.kt
create mode 100644 state-recover/appcore/logic/src/test/kotlin/linea/staterecover/BlobDecompressorAndDeserializerV1Test.kt
create mode 100644 state-recover/besu-plugin/build.gradle
create mode 100644 state-recover/besu-plugin/src/main/kotlin/linea/staterecover/clients/ExecutionLayerInProcessClient.kt
create mode 100644 state-recover/besu-plugin/src/main/kotlin/linea/staterecover/plugin/AppConfigurator.kt
create mode 100644 state-recover/besu-plugin/src/main/kotlin/linea/staterecover/plugin/BlockContextData.kt
create mode 100644 state-recover/besu-plugin/src/main/kotlin/linea/staterecover/plugin/BlockImporter.kt
create mode 100644 state-recover/besu-plugin/src/main/kotlin/linea/staterecover/plugin/LineaStateRecoverPlugin.kt
create mode 100644 state-recover/besu-plugin/src/main/kotlin/linea/staterecover/plugin/PluginOptions.kt
create mode 100644 state-recover/besu-plugin/src/main/kotlin/linea/staterecover/plugin/RecoveryModeManager.kt
create mode 100644 state-recover/besu-plugin/src/main/kotlin/linea/staterecover/plugin/TransactionMapper.kt
create mode 100644 state-recover/besu-plugin/src/main/resources/META-INF/services/org.hyperledger.besu.plugin.BesuPlugin
rename state-recover/clients/blobscan-client/src/main/kotlin/{build => }/linea/staterecover/clients/blobscan/BlobScanClient.kt (82%)
rename state-recover/clients/blobscan-client/src/main/kotlin/{build => }/linea/staterecover/clients/blobscan/VertxRestClient.kt (52%)
rename state-recover/clients/blobscan-client/src/test/kotlin/{build => }/linea/staterecover/clients/blobscan/BlobScanClientTest.kt (99%)
create mode 100644 state-recover/clients/eth-api/build.gradle
create mode 100644 state-recover/clients/eth-api/src/main/kotlin/linea/build/staterecover/clients/VertxTransactionDetailsClient.kt
create mode 100644 state-recover/test-cases/build.gradle
rename state-recover/{clients/smartcontract/src/integrationTest/kotlin/linea/build/staterecover/clients/smartcontract => test-cases/src/integrationTest/kotlin/linea/staterecover}/LineaSubmissionEventsClientIntTest.kt (88%)
create mode 100644 state-recover/test-cases/src/integrationTest/kotlin/linea/staterecover/StateRecoverAppIntTest.kt
create mode 100644 state-recover/test-cases/src/integrationTest/kotlin/linea/staterecover/StateRecoverAppWithFakeExecutionClientIntTest.kt
create mode 100644 state-recover/test-cases/src/integrationTest/kotlin/linea/staterecover/StateRecoveryManualReplayToLocalStackIntTest.kt
create mode 100644 state-recover/test-cases/src/integrationTest/resources/log4j2.xml
create mode 100644 state-recover/test-cases/src/main/kotlin/linea/staterecover/test/FakeExecutionLayerClient.kt
create mode 100644 state-recover/test-cases/src/main/kotlin/linea/staterecover/test/FakeStateManagerClientBasedOnBlobsRecords.kt
create mode 100644 state-recover/test-cases/src/test/kotlin/linea/staterecover/StateRecoverSepoliaWithFakeExecutionClientIntTest.kt
create mode 100644 state-recover/test-cases/src/test/resources/vertx-options.json
create mode 100644 testdata/coordinator/prover/v3/aggregation/responses/1-3-c582331fee9d97bf39b11a6681579c5478097d4af5eb2c97e872c798b03287eb-getZkAggregatedProof.json
create mode 100644 testdata/coordinator/prover/v3/aggregation/responses/11-13-523fe0caa8ea09a3787268f8bc8cfdbf9005d1e527ed656c4efd1ec39e60dee1-getZkAggregatedProof.json
create mode 100644 testdata/coordinator/prover/v3/aggregation/responses/14-16-193b46cfdb687e208772c266f87c91e78a3edb1e02de9888b0ed37bf8560eb30-getZkAggregatedProof.json
create mode 100644 testdata/coordinator/prover/v3/aggregation/responses/17-19-b615854a9075e73fdbdb0f22367d8e48c36997b28857712f018ba10e05f52759-getZkAggregatedProof.json
create mode 100644 testdata/coordinator/prover/v3/aggregation/responses/20-22-9e033347194ecf686585d4ddc81a602edc9afa61c9d8437c69a1f0981e66fb78-getZkAggregatedProof.json
create mode 100644 testdata/coordinator/prover/v3/aggregation/responses/23-25-1cdd5b5dd6cf38f123b1de80eb1d86ce47ba28a9689930db69175cc9976f4fa4-getZkAggregatedProof.json
create mode 100644 testdata/coordinator/prover/v3/aggregation/responses/26-28-655573aeabb826867531dedc1510fd1c7540e871ce2da96641b2e59ca659669a-getZkAggregatedProof.json
create mode 100644 testdata/coordinator/prover/v3/aggregation/responses/29-31-411b174b8760f03354ec0ae215a6caae21472b0788600ab1df3d6da896186a1e-getZkAggregatedProof.json
create mode 100644 testdata/coordinator/prover/v3/aggregation/responses/32-34-bb1a9a83d812c5a46ade32842936de46f693f72c2a2f314abfb166d316bd4825-getZkAggregatedProof.json
create mode 100644 testdata/coordinator/prover/v3/aggregation/responses/35-37-061a9f803c029a06b7b594602ea76d6cf6d9737c25ee5215759ffca6bd3fed3c-getZkAggregatedProof.json
create mode 100644 testdata/coordinator/prover/v3/aggregation/responses/38-40-5239c241ba71475fe11f8a4dfc04addf97c874a9bc2a371bb9cf5bc245e8982c-getZkAggregatedProof.json
create mode 100644 testdata/coordinator/prover/v3/aggregation/responses/4-6-ef72701818f1320dce22734cac21e65af315dd84dbb57e4ad7ecf32710e3be87-getZkAggregatedProof.json
create mode 100644 testdata/coordinator/prover/v3/aggregation/responses/41-43-c9a80177215ac57e589cf92189846270b286b70bd3845e8ed6f19734f5e0c88c-getZkAggregatedProof.json
create mode 100644 testdata/coordinator/prover/v3/aggregation/responses/44-46-78d88bad483bfe5a8f9e8fd1d3af3cb034d6248aa279b764b63279b2ba7f0f2c-getZkAggregatedProof.json
create mode 100644 testdata/coordinator/prover/v3/aggregation/responses/7-7-aa133bea94f49f4edbfe7488b1a7394ed2559243139ca15097356d8baedc3e65-getZkAggregatedProof.json
create mode 100644 testdata/coordinator/prover/v3/aggregation/responses/8-10-487dc52c1e22d32a1c38917b99ed120ddffdcb5effa6c5ecca536dedd6d4e2ba-getZkAggregatedProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/1-3-c185fbadf462de3a6c8517cbac3ba7402a14e939e1d77e3a515ca1c8a3f7d977-getZkBlobCompressionProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/11-13-e5f194ad53779deb52c2455e216ca447a842026238fd8143cbb7911f7aefd9e7-getZkBlobCompressionProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/14-16-8de7b2d25ebb3dd54040cc30cbe3a6333053816812bb33dca470e945eff7044c-getZkBlobCompressionProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/17-19-343fef4cdcb6d0ab0db8ea7da91820c8d21a80135608b990c0b4f40c8f48b837-getZkBlobCompressionProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/20-22-aea706d4657966f8e30e918e1097ffa0da19513b0be56a243cabd7d3a32358c7-getZkBlobCompressionProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/23-25-268a263e550eb02c8196d4b9e3cc06a55d87018f2e20ed7304da5f2f3f6bbe5b-getZkBlobCompressionProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/26-28-06851ec1f1ba875ffd3a08fa5b2f0d88ac9426c9ccd852973abe73bd9afc921d-getZkBlobCompressionProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/29-31-0602578e3a61f2be5afdd3ee34c6ac99e1e36a50450c75ef9dd78e50dddd3f8c-getZkBlobCompressionProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/32-34-a646621c48d374488e214c7e02a64d431ae0712f3bc817a3d5943914f2246831-getZkBlobCompressionProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/35-37-86dc4abc4be5dfa0ddf8f4b8b98783973bbcd82b5ceff8d39361fe151d4e2ee8-getZkBlobCompressionProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/38-40-dec8e24af04a4aa184d63b3f68066b7633c2099aa042bcb37a234c5ce4210446-getZkBlobCompressionProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/4-6-513ed85de5604294e15b683fb22532c07a25531d93f402f17bb4a4c83a91b025-getZkBlobCompressionProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/41-43-67b48d2e3c30f21caaffe8677e9c8a84f43ae1e7ee936f0f8c03c4941cf04695-getZkBlobCompressionProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/44-46-e3c210adb4a5b495db0a285094885c32b74bd6cc85bbe0e0b5a6cdf7e88387da-getZkBlobCompressionProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/47-47-dc73dc616fccf89ba4b33ba446a9b73b5a1836142e0b1be933b7283f6f2b8061-getZkBlobCompressionProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/7-7-7db9a7cbfd21211ecd77d8791894eca4478be04c38002a415dce9eea9a7d39cb-getZkBlobCompressionProof.json
create mode 100644 testdata/coordinator/prover/v3/compression/responses/8-10-e6a7703511076e3789cc25059b468940b2e91df262f11b95b9005f758482aed7-getZkBlobCompressionProof.json
diff --git a/Makefile b/Makefile
index 0621cca0b..5e8251a43 100644
--- a/Makefile
+++ b/Makefile
@@ -158,10 +158,12 @@ deploy-l2-evm-opcode-tester:
RPC_URL=http:\\localhost:8545/ \
npx ts-node local-deployments-artifacts/deployLondonEvmTestingFramework.ts
-execute-all-opcodes:
+
+evm-opcode-tester-execute-all-opcodes: OPCODE_TEST_CONTRACT_ADDRESS:=0x997FC3aF1F193Cbdc013060076c67A13e218980e
+evm-opcode-tester-execute-all-opcodes:
# WARNING: FOR LOCAL DEV ONLY - DO NOT REUSE THESE KEYS ELSEWHERE
cd contracts/; \
- OPCODE_TEST_CONTRACT_ADDRESS=0x997FC3aF1F193Cbdc013060076c67A13e218980e \
+ OPCODE_TEST_CONTRACT_ADDRESS=$(OPCODE_TEST_CONTRACT_ADDRESS) \
NUMBER_OF_RUNS=3 \
PRIVATE_KEY=0x1dd171cec7e2995408b5513004e8207fe88d6820aeff0d82463b3e41df251aae \
RPC_URL=http:\\localhost:8545/ \
@@ -216,11 +218,17 @@ deploy-contracts-minimal:
cd .. && \
$(MAKE) -j6 deploy-linea-rollup-v$(L1_CONTRACT_VERSION) deploy-l2messageservice
-start-all-staterecover: L1_CONTRACT_VERSION:=6
-start-all-staterecover: COMPOSE_PROFILES:=l1,l2,staterecover
-start-all-staterecover:
- L1_GENESIS_TIME=$(get_future_time) make start-whole-environment COMPOSE_PROFILES=$(COMPOSE_PROFILES)
- make deploy-contracts-minimal L1_CONTRACT_VERSION=$(L1_CONTRACT_VERSION)
+fresh-start-all-staterecover: COMPOSE_PROFILES:=l1,l2,staterecover
+fresh-start-all-staterecover: L1_CONTRACT_VERSION:=6
+fresh-start-all-staterecover:
+ make clean-environment
+ L1_GENESIS_TIME=$(get_future_time) make start-whole-environment-traces-v2 COMPOSE_PROFILES=$(COMPOSE_PROFILES)
+ $(MAKE) deploy-contracts-minimal L1_CONTRACT_VERSION=$(L1_CONTRACT_VERSION)
+
+fresh-start-staterecover-for-replay-only: COMPOSE_PROFILES:=l1,staterecover
+fresh-start-staterecover-for-replay-only:
+ make clean-environment
+ L1_GENESIS_TIME=$(get_future_time) make start-whole-environment-traces-v2 COMPOSE_PROFILES=$(COMPOSE_PROFILES)
testnet-start-l2:
docker compose -f docker/compose.yml -f docker/compose-testnet-sync.overrides.yml --profile l2 up -d
diff --git a/build.gradle b/build.gradle
index 46307076e..059745aa2 100644
--- a/build.gradle
+++ b/build.gradle
@@ -87,7 +87,7 @@ allprojects {
systemProperty("L1_RPC_URL", "http://localhost:8445")
systemProperty("L2_RPC_URL", "http://localhost:8545")
systemProperty("L1_GENESIS", "docker/config/l1-node/el/genesis.json")
- systemProperty("L2_GENESIS", "docker/config/linea-local-dev-genesis.json")
+ systemProperty("L2_GENESIS", "docker/config/linea-local-dev-genesis-PoA.json")
systemProperties["junit.jupiter.execution.timeout.default"] = "5 m" // 5 minutes
systemProperties["junit.jupiter.execution.parallel.enabled"] = true
@@ -203,7 +203,8 @@ dockerCompose {
"staterecover"
]
useComposeFiles = [
- "${project.rootDir.path}/docker/compose.yml"
+ "${project.rootDir.path}/docker/compose.yml",
+ "${project.rootDir.path}/docker/compose-local-dev-traces-v2.overrides.yml"
]
waitForHealthyStateTimeout = Duration.ofMinutes(3)
waitForTcpPorts = false
diff --git a/config/coordinator/coordinator-docker.config.toml b/config/coordinator/coordinator-docker.config.toml
index 62ce6851f..781bb0b67 100644
--- a/config/coordinator/coordinator-docker.config.toml
+++ b/config/coordinator/coordinator-docker.config.toml
@@ -126,8 +126,8 @@ fee-history-reward-percentile=15
last-hash-search-window=25
anchoring-receipt-polling-interval="PT01S"
max-receipt-retries=120
-# Number of children blocks to wait before considering a won't be reverted and elegible for conflation.
-# this a workaround to mitigate Geth fork issues with Clique PoA
+# Number of children blocks to wait before considering they won't be reverted and elegible for conflation.
+# this is a workaround to mitigate Geth fork issues with Clique PoA
# Coordinator will consider block as finalized after being included in the chain wtih children blocks-to-finalization
# Recommended: Geth sequencer minimum of 2, Besu sequencer minimum of 1, 0 is safe localy
blocks-to-finalization=0
@@ -155,7 +155,7 @@ aggregation-proofs-limit=3
aggregation-deadline="PT10S"
aggregation-coordinator-polling-interval="PT2S"
deadline-check-interval="PT8S"
-target-end-blocks=[]
+#target-end-blocks=[33, 90, 93]
[finalization-signer]
# Web3j/Web3signer
@@ -266,8 +266,8 @@ num-of-blocks-before-latest=4
storage-period="PT2M"
[conflation]
-blocks-limit=2
-conflation-deadline="PT6S" # =3*l2_block_time
+blocks-limit=3
+conflation-deadline="PT6S"
conflation-deadline-check-interval="PT3S"
conflation-deadline-last-block-confirmation-delay="PT2S" # recommended: at least 2 * blockInterval
diff --git a/coordinator/app/src/main/kotlin/net/consensys/zkevm/coordinator/app/L1DependentApp.kt b/coordinator/app/src/main/kotlin/net/consensys/zkevm/coordinator/app/L1DependentApp.kt
index 3dff8e2fb..4b286a997 100644
--- a/coordinator/app/src/main/kotlin/net/consensys/zkevm/coordinator/app/L1DependentApp.kt
+++ b/coordinator/app/src/main/kotlin/net/consensys/zkevm/coordinator/app/L1DependentApp.kt
@@ -4,6 +4,7 @@ import build.linea.clients.StateManagerClientV1
import build.linea.clients.StateManagerV1JsonRpcClient
import build.linea.contract.l1.LineaRollupSmartContractClientReadOnly
import build.linea.contract.l1.Web3JLineaRollupSmartContractClientReadOnly
+import build.linea.web3j.Web3JLogsClient
import io.vertx.core.Vertx
import kotlinx.datetime.Clock
import linea.encoding.BlockRLPEncoder
@@ -11,7 +12,6 @@ import net.consensys.linea.BlockNumberAndHash
import net.consensys.linea.blob.ShnarfCalculatorVersion
import net.consensys.linea.contract.Web3JL2MessageService
import net.consensys.linea.contract.Web3JL2MessageServiceLogsClient
-import net.consensys.linea.contract.Web3JLogsClient
import net.consensys.linea.contract.l1.GenesisStateProvider
import net.consensys.linea.ethereum.gaspricing.BoundableFeeCalculator
import net.consensys.linea.ethereum.gaspricing.FeesCalculator
diff --git a/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/SwitchProviderImplTest.kt b/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/SwitchProviderImplTest.kt
index 03c3d81ab..8e6b0d012 100644
--- a/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/SwitchProviderImplTest.kt
+++ b/coordinator/app/src/test/kotlin/net/consensys/zkevm/coordinator/app/SwitchProviderImplTest.kt
@@ -2,12 +2,12 @@
package net.consensys.zkevm.coordinator.app
+import build.linea.web3j.Web3JLogsClient
import io.vertx.junit5.Timeout
import io.vertx.junit5.VertxExtension
import io.vertx.junit5.VertxTestContext
import net.consensys.linea.contract.EIP1559GasProvider
import net.consensys.linea.contract.L2MessageService
-import net.consensys.linea.contract.Web3JLogsClient
import net.consensys.toULong
import net.consensys.zkevm.ethereum.coordination.conflation.upgrade.SwitchProvider
import net.consensys.zkevm.ethereum.signing.ECKeypairSigner
diff --git a/coordinator/clients/prover-client/file-based-client/src/main/kotlin/net/consensys/zkevm/coordinator/clients/prover/FileBasedExecutionProverClientV2.kt b/coordinator/clients/prover-client/file-based-client/src/main/kotlin/net/consensys/zkevm/coordinator/clients/prover/FileBasedExecutionProverClientV2.kt
index c1f34bd22..294c577b4 100644
--- a/coordinator/clients/prover-client/file-based-client/src/main/kotlin/net/consensys/zkevm/coordinator/clients/prover/FileBasedExecutionProverClientV2.kt
+++ b/coordinator/clients/prover-client/file-based-client/src/main/kotlin/net/consensys/zkevm/coordinator/clients/prover/FileBasedExecutionProverClientV2.kt
@@ -57,7 +57,7 @@ internal class ExecutionProofRequestDataDecorator(
return SafeFuture.collectAll(bridgeLogsSfList.stream())
.thenCombine(
- getBlockStateRootHash(request.blocks.first().number.toULong() - 1UL)
+ getBlockStateRootHash(request.blocks.first().number - 1UL)
) { blocksAndBridgeLogs, previousKeccakStateRootHash ->
BatchExecutionProofRequestDto(
zkParentStateRootHash = request.type2StateData.zkParentStateRootHash.encodeHex(),
diff --git a/coordinator/clients/smart-contract-client/build.gradle b/coordinator/clients/smart-contract-client/build.gradle
index f1418d28b..5851971dd 100644
--- a/coordinator/clients/smart-contract-client/build.gradle
+++ b/coordinator/clients/smart-contract-client/build.gradle
@@ -4,7 +4,7 @@ plugins {
dependencies {
implementation project(":jvm-libs:generic:extensions:kotlin")
- implementation project(':jvm-libs:linea:web3j-extensions')
+ api project(':jvm-libs:linea:web3j-extensions')
api project(':jvm-libs:linea:clients:linea-l1-contract-client')
api 'build.linea:l2-message-service-contract-client:0.0.1'
@@ -15,5 +15,4 @@ dependencies {
implementation project(path: ':coordinator:core')
implementation project(path: ':coordinator:ethereum:common')
testImplementation "io.vertx:vertx-junit5"
- testImplementation "com.github.tomakehurst:wiremock-jre8:${libs.versions.wiremock.get()}"
}
diff --git a/coordinator/clients/smart-contract-client/src/main/kotlin/net/consensys/linea/contract/Web3JContractAsyncHelper.kt b/coordinator/clients/smart-contract-client/src/main/kotlin/net/consensys/linea/contract/Web3JContractAsyncHelper.kt
index 2dbf36d8b..f90df0c54 100644
--- a/coordinator/clients/smart-contract-client/src/main/kotlin/net/consensys/linea/contract/Web3JContractAsyncHelper.kt
+++ b/coordinator/clients/smart-contract-client/src/main/kotlin/net/consensys/linea/contract/Web3JContractAsyncHelper.kt
@@ -254,7 +254,7 @@ class Web3JContractAsyncHelper(
dynamicMaxFeePerGas: ULong?,
dynamicMaxFeePerBlobGas: ULong? = null
) {
- val withBlob = maxFeePerBlobGas != null && dynamicMaxFeePerBlobGas != null
+ val withBlob = maxFeePerBlobGas != null || dynamicMaxFeePerBlobGas != null
log.info(
"$logMessagePrefix gas price caps: " +
"blobCarrying=$withBlob " +
@@ -263,8 +263,8 @@ class Web3JContractAsyncHelper(
"maxFeePerGas=${maxFeePerGas.toGWei()} GWei, " +
"dynamicMaxFeePerGas=${dynamicMaxFeePerGas?.toGWei()} GWei, " +
if (withBlob) {
- "maxFeePerBlobGas=${maxFeePerBlobGas!!.toGWei()} GWei, " +
- "dynamicMaxFeePerBlobGas=${dynamicMaxFeePerBlobGas!!.toGWei()} GWei"
+ "maxFeePerBlobGas=${maxFeePerBlobGas?.toGWei()} GWei, " +
+ "dynamicMaxFeePerBlobGas=${dynamicMaxFeePerBlobGas?.toGWei()} GWei"
} else {
""
}
diff --git a/coordinator/clients/smart-contract-client/src/main/kotlin/net/consensys/linea/contract/Web3JL2MessageServiceLogsClient.kt b/coordinator/clients/smart-contract-client/src/main/kotlin/net/consensys/linea/contract/Web3JL2MessageServiceLogsClient.kt
index c41bb8b4e..ee174c634 100644
--- a/coordinator/clients/smart-contract-client/src/main/kotlin/net/consensys/linea/contract/Web3JL2MessageServiceLogsClient.kt
+++ b/coordinator/clients/smart-contract-client/src/main/kotlin/net/consensys/linea/contract/Web3JL2MessageServiceLogsClient.kt
@@ -1,5 +1,6 @@
package net.consensys.linea.contract
+import build.linea.web3j.Web3JLogsClient
import net.consensys.toULong
import net.consensys.zkevm.coordinator.clients.L2MessageServiceLogsClient
import net.consensys.zkevm.domain.BridgeLogsData
diff --git a/coordinator/ethereum/blob-submitter/src/integrationTest/kotlin/net/consensys/zkevm/ethereum/finalization/BlobAndAggregationFinalizationIntTest.kt b/coordinator/ethereum/blob-submitter/src/integrationTest/kotlin/net/consensys/zkevm/ethereum/finalization/BlobAndAggregationFinalizationIntTest.kt
index 51733bbd5..88876b55e 100644
--- a/coordinator/ethereum/blob-submitter/src/integrationTest/kotlin/net/consensys/zkevm/ethereum/finalization/BlobAndAggregationFinalizationIntTest.kt
+++ b/coordinator/ethereum/blob-submitter/src/integrationTest/kotlin/net/consensys/zkevm/ethereum/finalization/BlobAndAggregationFinalizationIntTest.kt
@@ -185,7 +185,8 @@ class BlobAndAggregationFinalizationIntTest : CleanDbTestSuiteParallel() {
val blobsEndTime = blobs.last().endBlockTime
val endTime = if (aggEndTime > blobsEndTime) aggEndTime else blobsEndTime
- fakeClock.setTimeTo(endTime.plus(10.seconds))
+ // submission do the cutoff by minutes, so we need to add 1 minute to the end time
+ fakeClock.setTimeTo(endTime.plus(1.minutes))
blobSubmissionCoordinator.start()
aggregationFinalizationCoordinator.start()
diff --git a/coordinator/ethereum/blob-submitter/src/main/kotlin/net/consensys/zkevm/ethereum/submission/SwitchProviderImpl.kt b/coordinator/ethereum/blob-submitter/src/main/kotlin/net/consensys/zkevm/ethereum/submission/SwitchProviderImpl.kt
index 666f0b600..9dae2b93b 100644
--- a/coordinator/ethereum/blob-submitter/src/main/kotlin/net/consensys/zkevm/ethereum/submission/SwitchProviderImpl.kt
+++ b/coordinator/ethereum/blob-submitter/src/main/kotlin/net/consensys/zkevm/ethereum/submission/SwitchProviderImpl.kt
@@ -2,8 +2,8 @@
package net.consensys.zkevm.ethereum.submission
+import build.linea.web3j.Web3JLogsClient
import net.consensys.linea.contract.L2MessageService
-import net.consensys.linea.contract.Web3JLogsClient
import net.consensys.toULong
import net.consensys.zkevm.ethereum.coordination.conflation.upgrade.SwitchProvider
import org.apache.logging.log4j.LogManager
diff --git a/coordinator/ethereum/test-utils/src/main/kotlin/net/consensys/zkevm/ethereum/AccountManager.kt b/coordinator/ethereum/test-utils/src/main/kotlin/net/consensys/zkevm/ethereum/AccountManager.kt
index 36611739f..dc7c94229 100644
--- a/coordinator/ethereum/test-utils/src/main/kotlin/net/consensys/zkevm/ethereum/AccountManager.kt
+++ b/coordinator/ethereum/test-utils/src/main/kotlin/net/consensys/zkevm/ethereum/AccountManager.kt
@@ -228,7 +228,7 @@ object L1AccountManager : AccountManager by WhaleBasedAccountManager(
object L2AccountManager : AccountManager by WhaleBasedAccountManager(
web3jClient = Web3jClientManager.l2Client,
- genesisFile = getPathTo(System.getProperty("L2_GENESIS", "docker/config/linea-local-dev-genesis.json")),
+ genesisFile = getPathTo(System.getProperty("L2_GENESIS", "docker/config/linea-local-dev-genesis-PoA.json")),
log = LogManager.getLogger(L2AccountManager::class.java)
)
diff --git a/docker/compose.yml b/docker/compose.yml
index 3084a9f20..d9ce8ac3f 100644
--- a/docker/compose.yml
+++ b/docker/compose.yml
@@ -408,6 +408,11 @@ services:
condition: service_healthy
l1-node-genesis-generator:
condition: service_completed_successfully
+ healthcheck:
+ test: ["CMD-SHELL", "curl -f http://localhost:4000/eth/v1/node/health || exit 1"]
+ interval: 1s
+ timeout: 1s
+ retries: 120
command: [ "--config-file=/config/config-file.yaml" ]
volumes:
- ./config/l1-node/cl/teku.key:/config/keys/teku.key:ro
@@ -644,6 +649,10 @@ services:
condition: service_healthy
redis:
condition: service_healthy
+ l1-cl-node:
+ condition: service_healthy
+ l1-el-node:
+ condition: service_healthy
blobscan-indexer:
container_name: blobscan-indexer
@@ -662,6 +671,10 @@ services:
condition: service_healthy
blobscan-api:
condition: service_started
+ l1-cl-node:
+ condition: service_healthy
+ l1-el-node:
+ condition: service_healthy
redis:
container_name: redis
@@ -684,6 +697,95 @@ services:
l1network:
ipv4_address: 10.10.10.205
+ zkbesu-shomei-sr:
+ image: consensys/linea-besu-package:${SEQUENCER_TAG:-devnet-811f30b}
+ hostname: zkbesu-shomei-sr
+ container_name: zkbesu-shomei-sr
+ profiles: [ "external-to-monorepo", "staterecover" ]
+ privileged: true
+# restart: none
+ user: root
+ ports:
+ - "9145:8545" # http
+ - "9146:8546" # websockets
+ - "9150:8550"
+ - "10545:9545"
+ healthcheck:
+ test: [ "CMD-SHELL", "bash -c \"[ -f /tmp/pid ]\"" ]
+ interval: 1s
+ timeout: 1s
+ retries: 120
+ restart: "no"
+ networks:
+ l1network:
+ ipv4_address: 10.10.10.206
+ linea:
+ ipv4_address: 11.11.11.116
+ environment:
+ LOG4J_CONFIGURATION_FILE: /var/lib/besu/log4j.xml
+ L1_ROLLUP_CONTRACT_ADDRESS: ${L1_ROLLUP_CONTRACT_ADDRESS:-0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9}
+ entrypoint:
+ - /bin/bash
+ - -c
+ - |
+ chown -R besu:besu /opt/besu/plugins && \
+ ls -lh /opt/besu/plugins && \
+ sed -i '/^CLASSPATH/c\CLASSPATH=/opt/besu/lib/\*' /opt/besu/bin/besu && \
+ /opt/besu/bin/besu \
+ --config-file=/var/lib/besu/zkbesu-config.toml \
+ --genesis-file=/var/lib/besu/genesis.json \
+ --plugins=BesuShomeiRpcPlugin,ZkTrieLogPlugin,LineaStateRecoverPlugin \
+ --rpc-http-api=ADMIN,DEBUG,NET,ETH,WEB3,PLUGINS,MINER,SHOMEI \
+ --Xbonsai-limit-trie-logs-enabled=false \
+ --plugin-shomei-http-host="11.11.11.117" \
+ --plugin-shomei-http-port=8888 \
+ --plugin-staterecovery-l1-rpc-endpoint=http://l1-el-node:8545 \
+ --plugin-staterecovery-shomei-endpoint=http://shomei-sr:8888 \
+ --plugin-staterecovery-blobscan-endpoint=http://blobscan-api:4001 \
+ --plugin-staterecovery-linea-sequencer-beneficiary-address=0x6d976c9b8ceee705d4fe8699b44e5eb58242f484 \
+ --plugin-staterecovery-overriding-recovery-start-block-number=1 \
+ --plugin-staterecovery-l1-polling-interval=PT1S
+ volumes:
+ - ./config/zkbesu-shomei/zkbesu-config.toml:/var/lib/besu/zkbesu-config.toml:ro
+ - ./config/zkbesu-shomei/log4j-staterecovery.xml:/var/lib/besu/log4j.xml:ro
+ - ./config/linea-local-dev-genesis-PoA-besu.json/:/var/lib/besu/genesis.json:ro
+ - ../state-recover/besu-plugin/build/libs/linea-staterecover-plugin-0.0.1-rc2.jar:/opt/besu/lib/linea-staterecover-plugin-0.0.1-rc2.jar
+ - ../state-recover/besu-plugin/build/libs/linea-staterecover-plugin-0.0.1-rc2.jar:/opt/besu/plugins/linea-staterecover-plugin-0.0.1-rc2.jar
+
+ shomei-sr:
+ image: consensys/linea-shomei:2.3.0
+ hostname: shomei-sr
+ container_name: shomei-sr
+ profiles: [ "external-to-monorepo", "staterecover" ]
+ depends_on:
+ zkbesu-shomei-sr:
+ condition: service_started
+ privileged: true
+ user: root
+ ports:
+ - "8890:8888"
+ healthcheck:
+ test: [ "CMD-SHELL", "bash -c \"[ -f /data/shomei/LOCK ]\"" ]
+ interval: 1s
+ timeout: 1s
+ retries: 60
+ networks:
+ linea:
+ ipv4_address: 11.11.11.117
+ environment:
+ LOG4J_CONFIGURATION_FILE: /log4j.xml
+ command:
+ - --besu-rpc-http-host=11.11.11.116
+ - --besu-rpc-http-port=8545
+ - --rpc-http-host=11.11.11.117
+ - --rpc-http-host-allow-list=*
+ - --rpc-http-port=8888
+ - --min-confirmations-before-importing=0
+ - --trace-start-block-number=0
+ volumes:
+ - ./config/shomei/log4j.xml:/log4j.xml:ro
+ # - ../tmp/local/shomei:/data/shomei/:z
+
########################
# Observability stack
########################
diff --git a/docker/config/linea-local-dev-genesis.json b/docker/config/linea-local-dev-genesis.json
deleted file mode 100644
index b4d149078..000000000
--- a/docker/config/linea-local-dev-genesis.json
+++ /dev/null
@@ -1,147 +0,0 @@
-{
- "@WARNING": "THIS FILE IS FOR LOCAL DEVELOPMENT ONLY! DO NOT REUSE ELSEWHERE",
- "config": {
- "chainId": 1337,
- "homesteadBlock": 0,
- "eip150Block": 0,
- "eip155Block": 0,
- "eip158Block": 0,
- "byzantiumBlock": 0,
- "constantinopleBlock": 0,
- "petersburgBlock": 0,
- "istanbulBlock": 0,
- "berlinBlock": 0,
- "londonBlock": 0,
- "parisBlock": 0,
- "terminalTotalDifficulty": 0,
- "clique": {
- "period": 2,
- "epoch": 30000
- }
- },
- "coinbase": "0x0000000000000000000000000000000000000000",
- "difficulty": "0x1",
- "extraData": "0x00000000000000000000000000000000000000000000000000000000000000005064f2bafb300be5ea73aed3f4835e1a0256a5b30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "gasLimit": "0xa00000",
- "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
- "nonce": "0x0",
- "timestamp": "0x645580D1",
- "@WARNING": "FOR LOCAL DEV ONLY - DO NOT REUSE THESE KEYS ELSEWHERE",
- "alloc": {
- "1b9abeec3215d8ade8a33607f2cf0f4f60e5f0d0": {
- "privateKey": "0x1dd171cec7e2995408b5513004e8207fe88d6820aeff0d82463b3e41df251aae",
- "comment": "Contract deployer account",
- "balance": "90000000000000000000000"
- },
- "fe3b557e8fb62b89f4916b721be55ceb828dbd73": {
- "privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
- "comment": "account 1, can be used as end user",
- "balance": "90000000000000000000001"
- },
- "627306090abaB3A6e1400e9345bC60c78a8BEf57": {
- "privateKey": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3",
- "comment": "account 2, can be used as end user",
- "balance": "90000000000000000000002"
- },
- "f17f52151EbEF6C7334FAD080c5704D77216b732": {
- "privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f",
- "comment": "account 3, can be used as end user",
- "balance": "90000000000000000000003"
- },
- "6d26dcc30a1693043aefa35ed9171c16da53f275": {
- "privateKey": "0x47629fbb4a7ad7772b4d1cc92f26b325577b70f1ed5940e1859b92d690f8a2bf",
- "comment": "account 4, can be used as end user",
- "balance": "90000000000000000000004"
- },
- "e00cad48944330a60bbaedfbf2e0ac97e9762a1e": {
- "privateKey": "0x4f78823f38639b9ef15392eb8024ace1d7b991ea820b0dd36a15d14d1a6785",
- "comment": "account 5, can be used as end user",
- "balance": "90000000000000000000005"
- },
- "2257ae433e214df824eb2ade79d2b305ca61a4f4": {
- "privateKey": "0x327456c797d6300e11051c0c19b9dbe480fe57cdfcb8033d313e80c7c2e10369",
- "comment": "account 6, can be used as end user",
- "balance": "90000000000000000000006"
- },
- "0d4278da2f55cf21a014b7fee0a2cb799ce17ede": {
- "privateKey": "0x9ffda2814ee771e0af8018aeea65f9eabd47ea9f2a5b628a4571adeafea692d1",
- "comment": "account 7, can be used as end user",
- "balance": "90000000000000000000007"
- },
- "994f4c82683f666d13d03a131078f1b94777790c": {
- "privateKey": "0xcd3a170ec22b2f3e4aee76356df0c34712db8c24f8d836bce1e4a79299c87053",
- "comment": "account 8, can be used as end user",
- "balance": "90000000000000000000008"
- },
- "9d14ef14d4c90436a062efd7dc8354a7ded9712e": {
- "privateKey": "0x4a954bb197f7a27a5427f29180fbfd0b32ee0344b4f85c8184ca593cf152866a",
- "comment": "account 9, can be used as end user",
- "balance": "90000000000000000000009"
- },
- "29a6b94168f04956c6fd1a2c3fdd1f6f7c468148": {
- "privateKey": "0x745dda33b5d813bda7f52d646a56498c1539290f59d064b13161f84a1f0a7b4b",
- "comment": "account 10, can be used as end user",
- "balance": "900000000000000000000010"
- },
- "dca74800d7ce103a5e6a3f6028ab0963c46e7422": {
- "privateKey": "0x75b9700016469b0d7f12c0d6a0225cd9a59818a4bd1437cf9583ca0ffa1d111a",
- "comment": "account 11, can be used as end user",
- "balance": "900000000000000000000011"
- },
- "9ad149426800dc9e65754a5ceab6bc1f41cc92a7": {
- "privateKey": "0xe08f03f96ff2f4e107a50da222e281db39cd528c8c35e25a17f0a71a4d279da5",
- "comment": "account 12, can be used as end user",
- "balance": "900000000000000000000012"
- },
- "b3c150df38e91149e260c3233f3121810d4d2976": {
- "privateKey": "0x7303d2fadd895018075cbe76d8a700bc65b4a1b8641b97d660533f0e029e3954",
- "comment": "account 13, can be used as end user",
- "balance": "900000000000000000000013"
- },
- "42232eab8cfd6b489efe79d3bdcc12f07a9fbac6": {
- "privateKey": "0xc5453712de35e7dc2c599b5f86df5d4f0de442d86a2865cfe557acd6d131aa6f",
- "comment": "account 14, can be used as end user",
- "balance": "900000000000000000000014"
- },
- "30b080749e44112c3e679c5e4117dd2d884ec7da": {
- "privateKey": "0xa8cc1b4bf5cd228cfe63c1b73a5515721e72b487cf8b82a285023aa0ed1ef839",
- "comment": "account 15, can be used as end user",
- "balance": "900000000000000000000015"
- },
- "82f93ea98b24441dc3e0b2413cc1cbb02f33d7e5": {
- "privateKey": "0x8c1c8a65947b79ef919261364e9044d89ffe26fb764d8cd72db0446d6cf56664",
- "comment": "account 16, can be used as end user",
- "balance": "900000000000000000000016"
- },
- "bae3c3fcd73ccf7755ec8a10664f218ad6bbc775": {
- "privateKey": "0xb35972d9380d1be620a2c61da77f68f127ef248ec55e1bc6033d20a7e13ef3fa",
- "comment": "account 17, can be used as end user",
- "balance": "900000000000000000000017"
- },
- "54d450f4d728da50f1271a1700b42657940324aa": {
- "privateKey": "0x234d87442cf7d43841fbe280febcdfabfb646added67bc19f7e42a5483f614c4",
- "comment": "account 18, can be used as end user",
- "balance": "900000000000000000000018"
- },
- "d42e308fc964b71e18126df469c21b0d7bcb86cc": {
- "privateKey": "0x4d01ae6487860981699236a58b68f807ee5f17b12df5740b85cf4c4653be0f55",
- "comment": "Message anchorer account",
- "balance": "900000000000000000000019"
- },
- "c8c92fe825d8930b9357c006e0af160dfa727a62": {
- "privateKey": "0xfcf854e0a0bc6fd7e97d7050e61a362c915cecd6767a32267b22e8b7af572e58",
- "comment": "account 20, can be used as end user",
- "balance": "900000000000000000000020"
- },
- "8cdcc370846c9f669489227465f80e6cc4ecd050": {
- "privateKey": "0xb17202c37cce9498e6f7dcdc1abd207802d09b5eee96677ea219ac867a198b91",
- "comment": "Account used for smart contract deployment on L1 and L2",
- "balance": "90000000000000000000000"
- },
- "d0584d4d37157f7105a4b41ed8ecbdfafdb2547f": {
- "privateKey": "0x202454d1b4e72c41ebf58150030f649648d3cf5590297fb6718e27039ed9c86d",
- "comment": "Operator account",
- "balance": "90000000000000000000000"
- }
- }
-}
diff --git a/docker/config/shomei/log4j.xml b/docker/config/shomei/log4j.xml
index 15df621c1..46bc5b2f8 100644
--- a/docker/config/shomei/log4j.xml
+++ b/docker/config/shomei/log4j.xml
@@ -6,7 +6,7 @@
-
+
diff --git a/docker/config/traces-node-v2/log4j.xml b/docker/config/traces-node-v2/log4j.xml
index 4fce5c508..f7d311869 100644
--- a/docker/config/traces-node-v2/log4j.xml
+++ b/docker/config/traces-node-v2/log4j.xml
@@ -25,7 +25,7 @@
-
+
diff --git a/docker/config/traces-node-v2/traces-node-v2-config.toml b/docker/config/traces-node-v2/traces-node-v2-config.toml
index a38c5d8e7..09ca48cd2 100644
--- a/docker/config/traces-node-v2/traces-node-v2-config.toml
+++ b/docker/config/traces-node-v2/traces-node-v2-config.toml
@@ -38,7 +38,7 @@ data-storage-format="BONSAI"
# plugins
plugins=["TracerReadinessPlugin","TracesEndpointServicePlugin","LineCountsEndpointServicePlugin","CaptureEndpointServicePlugin"]
plugin-linea-conflated-trace-generation-traces-output-path="/data/traces/v2/conflated"
-plugin-linea-rpc-concurrent-requests-limit=1
+plugin-linea-rpc-concurrent-requests-limit=2
plugin-linea-tracer-readiness-server-host="0.0.0.0"
plugin-linea-tracer-readiness-server-port=8548
plugin-linea-tracer-readiness-max-blocks-behind=5
diff --git a/docker/config/zkbesu-shomei/log4j-staterecovery.xml b/docker/config/zkbesu-shomei/log4j-staterecovery.xml
new file mode 100644
index 000000000..6e5ada67a
--- /dev/null
+++ b/docker/config/zkbesu-shomei/log4j-staterecovery.xml
@@ -0,0 +1,53 @@
+
+
+
+ INFO
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docker/config/zkbesu-shomei/log4j.xml b/docker/config/zkbesu-shomei/log4j.xml
index 56c746fb5..144906b8d 100644
--- a/docker/config/zkbesu-shomei/log4j.xml
+++ b/docker/config/zkbesu-shomei/log4j.xml
@@ -1,7 +1,7 @@
- WARN
+ INFO
diff --git a/docker/linea-sepolia/genesis.json b/docker/linea-sepolia/genesis.json
index 037bd7a2c..09f520d32 100644
--- a/docker/linea-sepolia/genesis.json
+++ b/docker/linea-sepolia/genesis.json
@@ -19,7 +19,7 @@
"nonce": "0x0",
"timestamp": "0x6391BFF3",
"extraData": "0x00000000000000000000000000000000000000000000000000000000000000004D517Aef039A48b3B6bF921e210b7551C8E371070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "gasLimit": "0x1C9C380",
+ "gasLimit": "0x3a2c940",
"difficulty": "0x1",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
@@ -814,4 +814,4 @@
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
- }
\ No newline at end of file
+ }
diff --git a/docker/scripts/file-downloader.sh b/docker/scripts/file-downloader.sh
deleted file mode 100644
index 1de52d8e7..000000000
--- a/docker/scripts/file-downloader.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/env bash
-
-if [ $# -lt 2 ]; then
- echo "Usage: $0 file_url destination_folder"
- echo "Example: $0 https://example.com/somefile.txt /path/to/destination/"
- exit
-fi
-
-check_and_download_file() {
- local file_url="$1"
- local directory="$2"
- local filename="${file_url##*/}" # Extracts the filename from the URL
-
- # Check if the file exists in the directory
- if [[ ! -f "$directory/$filename" ]]; then
- # File does not exist, download it
- echo "Downloading $file_url ..."
- wget "$file_url" -P "$directory"
- echo "Download complete!"
- else
- echo "File $filename already exists in $directory."
- fi
-}
-echo "$0 $1 $2"
-check_and_download_file "$1" "$2"
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 670b1201d..509df13fd 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -9,6 +9,7 @@ jreleaser = { group = "org.jreleaser", name = "jreleaser-gradle-plugin", version
[versions]
besu = "24.12.2"
+bouncycastle = "1.79"
caffeine = "3.1.6"
hoplite = "2.7.5"
jackson = "2.18.0"
@@ -19,7 +20,7 @@ ktlint = "0.47.0"
log4j = "2.20.0"
micrometer = "1.8.4"
netty = "4.1.92.Final"
-picoli = "4.7.1"
+picoli = "4.7.6"
restassured = "5.3.0"
teku = "23.1.1"
tuweni = "2.4.2"
@@ -28,5 +29,6 @@ vertx = "4.5.0"
web3j = "4.12.2"
wiremock = "3.0.1"
jsonUnit = "3.4.1"
+slf4j="1.7.36"
blobCompressor = "0.0.4"
blobShnarfCalculator = "0.0.4"
diff --git a/jvm-libs/generic/extensions/kotlin/src/main/kotlin/net/consensys/TypingsExtensions.kt b/jvm-libs/generic/extensions/kotlin/src/main/kotlin/net/consensys/TypingsExtensions.kt
index 650de984b..5114a4429 100644
--- a/jvm-libs/generic/extensions/kotlin/src/main/kotlin/net/consensys/TypingsExtensions.kt
+++ b/jvm-libs/generic/extensions/kotlin/src/main/kotlin/net/consensys/TypingsExtensions.kt
@@ -66,6 +66,16 @@ fun ULong.toGWei(): Double = this.toDouble().toGWei()
*/
fun ULong.Companion.fromHexString(value: String): ULong = value.removePrefix("0x").toULong(16)
+fun ULongRange.intersection(other: ULongRange): ULongRange {
+ val start = maxOf(this.first, other.first)
+ val end = minOf(this.last, other.last)
+ return if (start <= end) {
+ start..end
+ } else {
+ ULongRange.EMPTY
+ }
+}
+
fun > ClosedRange.toIntervalString(): String {
val size = if (start <= endInclusive) {
this.endInclusive.toString().toBigDecimal() - this.start.toString().toBigDecimal() + 1.toBigDecimal()
diff --git a/jvm-libs/generic/json-rpc/src/testFixtures/kotlin/linea/jsonrpc/TestingJsonRpcServer.kt b/jvm-libs/generic/json-rpc/src/testFixtures/kotlin/linea/jsonrpc/TestingJsonRpcServer.kt
index 64921a6b7..44e9591b2 100644
--- a/jvm-libs/generic/json-rpc/src/testFixtures/kotlin/linea/jsonrpc/TestingJsonRpcServer.kt
+++ b/jvm-libs/generic/json-rpc/src/testFixtures/kotlin/linea/jsonrpc/TestingJsonRpcServer.kt
@@ -31,7 +31,7 @@ open class TestingJsonRpcServer(
port: Int = 0,
val apiPath: String = "/",
val recordRequestsResponses: Boolean = false,
- val serverName: String = "FakeJsonRpcServer",
+ val serverName: String = "TestingJsonRpcServer",
loggerName: String = serverName,
val vertx: Vertx = Vertx.vertx(),
val responseObjectMapper: ObjectMapper = jacksonObjectMapper(),
diff --git a/jvm-libs/generic/logging/src/main/kotlin/linea/logging/TimeMeasureLogger.kt b/jvm-libs/generic/logging/src/main/kotlin/linea/logging/TimeMeasureLogger.kt
new file mode 100644
index 000000000..72ddf85dd
--- /dev/null
+++ b/jvm-libs/generic/logging/src/main/kotlin/linea/logging/TimeMeasureLogger.kt
@@ -0,0 +1,38 @@
+package linea.logging
+
+import org.apache.logging.log4j.Level
+import org.apache.logging.log4j.Logger
+import kotlin.time.measureTime
+
+/**
+ * This is more for debugging purposes, to measure the time taken by a certain action and log it.
+ * For production code, consider using metrics.
+ */
+fun measureTimeAndLog(
+ logger: Logger,
+ logLevel: Level = Level.DEBUG,
+ logMessageProvider: (duration: kotlin.time.Duration, result: T) -> String,
+ action: () -> T
+): T {
+ var value: T
+ val duration = measureTime {
+ value = action()
+ }
+ if (logger.isEnabled(logLevel)) {
+ logger.log(logLevel, logMessageProvider(duration, value))
+ }
+ return value
+}
+
+class MeasureLogger(
+ private val logger: Logger,
+ private val logLevel: Level = Level.DEBUG
+) {
+ fun measureTimeAndLog(
+ logLevel: Level = this.logLevel,
+ logMessageProvider: (duration: kotlin.time.Duration, result: T) -> String,
+ action: () -> T
+ ): T {
+ return measureTimeAndLog(logger, logLevel, logMessageProvider, action)
+ }
+}
diff --git a/jvm-libs/generic/logging/src/main/kotlin/net/consensys/linea/logging/JsonRpcRequestResponseLogger.kt b/jvm-libs/generic/logging/src/main/kotlin/net/consensys/linea/logging/JsonRpcRequestResponseLogger.kt
index c47ecf817..f761174cb 100644
--- a/jvm-libs/generic/logging/src/main/kotlin/net/consensys/linea/logging/JsonRpcRequestResponseLogger.kt
+++ b/jvm-libs/generic/logging/src/main/kotlin/net/consensys/linea/logging/JsonRpcRequestResponseLogger.kt
@@ -26,12 +26,11 @@ class MinimalInLineJsonRpcLogger(
) : JsonRpcRequestResponseLogger {
private fun logRequestOnLevel(level: Level, endpoint: String, jsonBody: String, throwable: Throwable?) {
- val message = if (throwable == null) {
- "--> {} {}"
+ if (throwable == null) {
+ logger.log(level, "--> {} {}", endpoint, jsonBody)
} else {
- "--> {} {} failed with error={}"
+ logger.log(level, "--> {} {} failed with error={}", endpoint, jsonBody, throwable.message, throwable)
}
- logger.log(level, message, endpoint, jsonBody, throwable?.message, throwable)
}
override fun logRequest(endpoint: String, jsonBody: String, throwable: Throwable?) {
@@ -54,19 +53,23 @@ class MinimalInLineJsonRpcLogger(
logRequestOnLevel(logLevel, maskedEndpoint, requestBody, null)
}
- val message = if (failureCause == null) {
- "<-- {} {} {}"
+ if (failureCause == null) {
+ logger.log(
+ logLevel,
+ "<-- {} {} {}",
+ maskedEndpoint,
+ responseStatusCode,
+ responseBody
+ )
} else {
- "<-- {} {} {} failed with error={}"
+ logger.log(
+ logLevel,
+ "<-- {} {} {} failed with error={}",
+ maskedEndpoint,
+ responseStatusCode,
+ responseBody,
+ failureCause.message
+ )
}
-
- logger.log(
- logLevel,
- message,
- maskedEndpoint,
- responseStatusCode,
- responseBody,
- failureCause?.message
- )
}
}
diff --git a/jvm-libs/generic/logging/src/test/kotlin/net/consensys/linea/logging/MinimalInLineJsonRpcLoggerTest.kt b/jvm-libs/generic/logging/src/test/kotlin/net/consensys/linea/logging/MinimalInLineJsonRpcLoggerTest.kt
index 680ab3111..dc3dd24b0 100644
--- a/jvm-libs/generic/logging/src/test/kotlin/net/consensys/linea/logging/MinimalInLineJsonRpcLoggerTest.kt
+++ b/jvm-libs/generic/logging/src/test/kotlin/net/consensys/linea/logging/MinimalInLineJsonRpcLoggerTest.kt
@@ -36,7 +36,7 @@ class MinimalInLineJsonRpcLoggerTest {
fun `logRequest logs request with correct level and format`() {
minimalInLineJsonRpcLogger.logRequest("testEndpoint", jsonRequestBody)
- verify(logger).log(eq(Level.DEBUG), eq("--> {} {}"), eq("testEndpoint"), eq(jsonRequestBody), eq(null), eq(null))
+ verify(logger).log(eq(Level.DEBUG), eq("--> {} {}"), eq("testEndpoint"), eq(jsonRequestBody))
}
@Test
@@ -63,8 +63,7 @@ class MinimalInLineJsonRpcLoggerTest {
eq("<-- {} {} {}"),
eq("testEndpoint"),
eq(200),
- eq(jsonSuccessResponse),
- eq(null)
+ eq(jsonSuccessResponse)
)
}
@@ -73,7 +72,7 @@ class MinimalInLineJsonRpcLoggerTest {
val exception = RuntimeException("Test exception")
minimalInLineJsonRpcLogger.logResponse("testEndpoint", 500, jsonRequestBody, jsonErrorResponse, exception)
- verify(logger).log(eq(Level.WARN), eq("--> {} {}"), eq("testEndpoint"), eq(jsonRequestBody), eq(null), eq(null))
+ verify(logger).log(eq(Level.WARN), eq("--> {} {}"), eq("testEndpoint"), eq(jsonRequestBody))
verify(logger).log(
eq(Level.WARN),
eq("<-- {} {} {} failed with error={}"),
diff --git a/jvm-libs/generic/serialization/jackson/src/main/kotlin/build/linea/s11n/jackson/InstantAsHexNumberSerDe.kt b/jvm-libs/generic/serialization/jackson/src/main/kotlin/build/linea/s11n/jackson/InstantAsHexNumberSerDe.kt
new file mode 100644
index 000000000..533d0abb1
--- /dev/null
+++ b/jvm-libs/generic/serialization/jackson/src/main/kotlin/build/linea/s11n/jackson/InstantAsHexNumberSerDe.kt
@@ -0,0 +1,21 @@
+package build.linea.s11n.jackson
+
+import com.fasterxml.jackson.core.JsonGenerator
+import com.fasterxml.jackson.core.JsonParser
+import com.fasterxml.jackson.databind.DeserializationContext
+import com.fasterxml.jackson.databind.JsonDeserializer
+import com.fasterxml.jackson.databind.JsonSerializer
+import com.fasterxml.jackson.databind.SerializerProvider
+import kotlinx.datetime.Instant
+
+object InstantAsHexNumberSerializer : JsonSerializer() {
+ override fun serialize(value: Instant, gen: JsonGenerator, serializers: SerializerProvider) {
+ gen.writeString("0x${value.epochSeconds.toString(16)}")
+ }
+}
+
+object InstantAsHexNumberDeserializer : JsonDeserializer() {
+ override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Instant {
+ return Instant.fromEpochSeconds(p.text.replace("0x", "").toLong(16))
+ }
+}
diff --git a/jvm-libs/generic/serialization/jackson/src/main/kotlin/build/linea/s11n/jackson/InstantISO8601SerDe.kt b/jvm-libs/generic/serialization/jackson/src/main/kotlin/build/linea/s11n/jackson/InstantISO8601SerDe.kt
index 3c1d671ec..f16752206 100644
--- a/jvm-libs/generic/serialization/jackson/src/main/kotlin/build/linea/s11n/jackson/InstantISO8601SerDe.kt
+++ b/jvm-libs/generic/serialization/jackson/src/main/kotlin/build/linea/s11n/jackson/InstantISO8601SerDe.kt
@@ -14,7 +14,6 @@ object InstantISO8601Serializer : JsonSerializer() {
}
}
-// To uncomment and add the tests when necessary
object InstantISO8601Deserializer : JsonDeserializer() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): Instant {
return Instant.parse(p.text)
diff --git a/jvm-libs/generic/serialization/jackson/src/test/kotlin/build/linea/s11n/jackson/InstantAsHexNumberSerDeTest.kt b/jvm-libs/generic/serialization/jackson/src/test/kotlin/build/linea/s11n/jackson/InstantAsHexNumberSerDeTest.kt
new file mode 100644
index 000000000..16b702b9b
--- /dev/null
+++ b/jvm-libs/generic/serialization/jackson/src/test/kotlin/build/linea/s11n/jackson/InstantAsHexNumberSerDeTest.kt
@@ -0,0 +1,56 @@
+package build.linea.s11n.jackson
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.databind.module.SimpleModule
+import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
+import kotlinx.datetime.Instant
+import net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+
+class InstantAsHexNumberSerDeTest {
+ private lateinit var objectMapper: ObjectMapper
+
+ @BeforeEach
+ fun setUp() {
+ objectMapper = jacksonObjectMapper()
+ .registerModules(
+ SimpleModule().apply {
+ this.addSerializer(Instant::class.java, InstantAsHexNumberSerializer)
+ this.addDeserializer(Instant::class.java, InstantAsHexNumberDeserializer)
+ }
+ )
+ }
+
+ @Test
+ fun instantSerDeDeSerialization() {
+ data class SomeObject(
+ // Int
+ val instantNull: Instant? = null,
+ // 2021-01-02T09:00:45Z UTC,
+ val instantUTC: Instant = Instant.fromEpochSeconds(1609578045),
+ // 2021-07-01T08:00:45Z UTC
+ val instantUTCDST: Instant = Instant.fromEpochSeconds(1625126445),
+ // 2021-01-02T09:00:45+01:30 UTC+01:30,
+ val instantUTCPlus: Instant = Instant.fromEpochSeconds(1609572645),
+ // 2021-01-02T09:00:45-01:30" UTC-01:30
+ val instantUTCMinus: Instant = Instant.fromEpochSeconds(1609583445)
+ )
+
+ val expectedJson = """
+ {
+ "instantNull": null,
+ "instantUTC": "0x5ff0363d",
+ "instantUTCDST": "0x60dd762d",
+ "instantUTCPlus": "0x5ff02125",
+ "instantUTCMinus": "0x5ff04b55"
+ }
+ """.trimIndent()
+
+ // assert serialization
+ assertThatJson(objectMapper.writeValueAsString(SomeObject())).isEqualTo(expectedJson)
+
+ // assert deserialization
+ assertThatJson(objectMapper.readValue(expectedJson, SomeObject::class.java)).isEqualTo(SomeObject())
+ }
+}
diff --git a/jvm-libs/linea/besu-libs/build.gradle b/jvm-libs/linea/besu-libs/build.gradle
index e9b797c88..4c91d9662 100644
--- a/jvm-libs/linea/besu-libs/build.gradle
+++ b/jvm-libs/linea/besu-libs/build.gradle
@@ -3,27 +3,30 @@ plugins {
id 'java-library'
}
-def besuArtifactGroup="org.hyperledger.besu"
+//def besuArtifactGroup="org.hyperledger.besu"
+//def besuVersion=libs.versions.besu.get()
+def besuArtifactGroup="io.consensys.linea-besu"
+def besuVersion="24.12-develop-2098dd2"
dependencies {
- api("${besuArtifactGroup}:besu-datatypes:${libs.versions.besu.get()}") {
+ api("${besuArtifactGroup}:besu-datatypes:${besuVersion}") {
transitive = false
}
- api("${besuArtifactGroup}:evm:${libs.versions.besu.get()}") {
+ api("${besuArtifactGroup}:evm:${besuVersion}") {
transitive = false
}
- api("${besuArtifactGroup}.internal:core:${libs.versions.besu.get()}") {
+ api("${besuArtifactGroup}.internal:core:${besuVersion}") {
transitive = false
}
- api("${besuArtifactGroup}.internal:algorithms:${libs.versions.besu.get()}") {
+ api("${besuArtifactGroup}.internal:algorithms:${besuVersion}") {
transitive = false
}
- api("${besuArtifactGroup}:plugin-api:${libs.versions.besu.get()}") {
+ api("${besuArtifactGroup}:plugin-api:${besuVersion}") {
transitive = false
}
- api("${besuArtifactGroup}.internal:rlp:${libs.versions.besu.get()}") {
+ api("${besuArtifactGroup}.internal:rlp:${besuVersion}") {
transitive = false
}
@@ -34,4 +37,11 @@ dependencies {
api("io.tmio:tuweni-units:${libs.versions.tuweni.get()}") {
transitive = false
}
+
+ implementation("org.bouncycastle:bcpkix-jdk18on:${libs.versions.bouncycastle.get()}") {
+ because "necessary for besu Transaction object that verifies signatures"
+ }
+ implementation("org.bouncycastle:bcprov-jdk18on:${libs.versions.bouncycastle.get()}") {
+ because "necessary for besu Transaction object that verifies signatures"
+ }
}
diff --git a/jvm-libs/linea/besu-rlp-and-mappers/build.gradle b/jvm-libs/linea/besu-rlp-and-mappers/build.gradle
index 3e1576a6b..7e3bbea5c 100644
--- a/jvm-libs/linea/besu-rlp-and-mappers/build.gradle
+++ b/jvm-libs/linea/besu-rlp-and-mappers/build.gradle
@@ -7,5 +7,8 @@ dependencies {
api(project(':jvm-libs:generic:extensions:futures'))
api(project(':jvm-libs:linea:core:domain-models'))
api(project(':jvm-libs:linea:besu-libs'))
+ implementation("org.slf4j:slf4j-api:${libs.versions.slf4j.get()}") {
+ because("Besu RLP uses SLF4J")
+ }
api "io.vertx:vertx-core"
}
diff --git a/jvm-libs/linea/blob-compressor/build.gradle b/jvm-libs/linea/blob-compressor/build.gradle
index 647c19cd8..68139ec08 100644
--- a/jvm-libs/linea/blob-compressor/build.gradle
+++ b/jvm-libs/linea/blob-compressor/build.gradle
@@ -11,7 +11,11 @@ dependencies {
implementation project(":jvm-libs:generic:extensions:kotlin")
implementation "org.apache.logging.log4j:log4j-api:${libs.versions.log4j.get()}"
implementation "org.apache.logging.log4j:log4j-core:${libs.versions.log4j.get()}"
+
testImplementation project(":jvm-libs:linea:blob-shnarf-calculator")
+ testFixturesImplementation project(':jvm-libs:linea:besu-libs')
+ testFixturesImplementation project(':jvm-libs:linea:besu-rlp-and-mappers')
+ testFixturesImplementation(project(":jvm-libs:linea:testing:file-system"))
}
jar {
diff --git a/jvm-libs/linea/blob-compressor/src/main/kotlin/linea/blob/BlobCompressor.kt b/jvm-libs/linea/blob-compressor/src/main/kotlin/linea/blob/BlobCompressor.kt
index dc272c896..58f36cccf 100644
--- a/jvm-libs/linea/blob-compressor/src/main/kotlin/linea/blob/BlobCompressor.kt
+++ b/jvm-libs/linea/blob-compressor/src/main/kotlin/linea/blob/BlobCompressor.kt
@@ -24,6 +24,12 @@ interface BlobCompressor {
fun getCompressedData(): ByteArray
fun reset()
+ fun getCompressedDataAndReset(): ByteArray {
+ val compressedData = getCompressedData()
+ reset()
+ return compressedData
+ }
+
data class AppendResult(
// returns false if last chunk would go over dataLimit. Does not append last block.
val blockAppended: Boolean,
diff --git a/jvm-libs/linea/blob-compressor/src/test/kotlin/linea/blob/GoBackedBlobCompressorTest.kt b/jvm-libs/linea/blob-compressor/src/test/kotlin/linea/blob/GoBackedBlobCompressorTest.kt
index 83e3cd30d..faf20dd1b 100644
--- a/jvm-libs/linea/blob-compressor/src/test/kotlin/linea/blob/GoBackedBlobCompressorTest.kt
+++ b/jvm-libs/linea/blob-compressor/src/test/kotlin/linea/blob/GoBackedBlobCompressorTest.kt
@@ -12,7 +12,7 @@ import kotlin.random.Random
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class GoBackedBlobCompressorTest {
companion object {
- private const val DATA_LIMIT = 16 * 1024
+ private const val DATA_LIMIT = 24 * 1024
private val TEST_DATA = CompressorTestData.blocksRlpEncoded
private val compressor = GoBackedBlobCompressor.getInstance(BlobCompressorVersion.V0_1_0, DATA_LIMIT.toUInt())
}
@@ -41,14 +41,20 @@ class GoBackedBlobCompressorTest {
@Test
fun `test compression data limit exceeded`() {
- val blocks = TEST_DATA.iterator()
+ var blocks = TEST_DATA.iterator()
var result = compressor.appendBlock(blocks.next())
- while (result.blockAppended && blocks.hasNext()) {
+ // at least one block should be appended
+ assertThat(result.blockAppended).isTrue()
+ while (result.blockAppended) {
val blockRlp = blocks.next()
val canAppend = compressor.canAppendBlock(blockRlp)
result = compressor.appendBlock(blockRlp)
// assert consistency between canAppendBlock and appendBlock
assertThat(canAppend).isEqualTo(result.blockAppended)
+ if (!blocks.hasNext()) {
+ // recompress again, until the limit is reached
+ blocks = TEST_DATA.iterator()
+ }
}
assertThat(result.blockAppended).isFalse()
assertThat(result.compressedSizeBefore).isGreaterThan(0)
diff --git a/jvm-libs/linea/blob-compressor/src/test/kotlin/net/consensys/linea/blob/GoNativeCompressorAndShnarfCalculatorIntTest.kt b/jvm-libs/linea/blob-compressor/src/test/kotlin/net/consensys/linea/blob/GoNativeCompressorAndShnarfCalculatorIntTest.kt
index 1f58c75b1..efcbb3bb9 100644
--- a/jvm-libs/linea/blob-compressor/src/test/kotlin/net/consensys/linea/blob/GoNativeCompressorAndShnarfCalculatorIntTest.kt
+++ b/jvm-libs/linea/blob-compressor/src/test/kotlin/net/consensys/linea/blob/GoNativeCompressorAndShnarfCalculatorIntTest.kt
@@ -12,7 +12,7 @@ import java.util.Base64
import kotlin.random.Random
class GoNativeCompressorAndShnarfCalculatorIntTest {
- private val DATA_LIMIT = 16 * 1024
+ private val DATA_LIMIT = 128 * 1024
private lateinit var compressor: GoNativeBlobCompressor
private lateinit var shnarfCalculator: GoNativeBlobShnarfCalculator
@@ -44,7 +44,7 @@ class GoNativeCompressorAndShnarfCalculatorIntTest {
@Test
fun `compressed size estimation should be consistent with blob maker output`() {
- testCompressedSizeSstimationIsConsistentWithBlobMakerOutput()
+ testCompressedSizeEstimationIsConsistentWithBlobMakerOutput()
}
}
@@ -72,7 +72,7 @@ class GoNativeCompressorAndShnarfCalculatorIntTest {
@Test
fun `compressed size estimation should be consistent with blob maker output`() {
- testCompressedSizeSstimationIsConsistentWithBlobMakerOutput()
+ testCompressedSizeEstimationIsConsistentWithBlobMakerOutput()
}
}
@@ -201,7 +201,7 @@ class GoNativeCompressorAndShnarfCalculatorIntTest {
resultAsserterFn(result)
}
- fun testCompressedSizeSstimationIsConsistentWithBlobMakerOutput() {
+ fun testCompressedSizeEstimationIsConsistentWithBlobMakerOutput() {
val block = CompressorTestData.blocksRlpEncoded.first()
// Write the block to the blob maker and get the effective compressed size
@@ -225,6 +225,6 @@ class GoNativeCompressorAndShnarfCalculatorIntTest {
// min compressed size should always be strictly bigger than the size returned
// by the blob maker minus the header size
- assertTrue((compressedSizeWithHeader - estimatedHeaderSizePacked) < compressedSize)
+ assertThat(compressedSizeWithHeader - estimatedHeaderSizePacked).isLessThanOrEqualTo(compressedSize)
}
}
diff --git a/jvm-libs/linea/blob-compressor/src/testFixtures/kotlin/net/consensys/linea/nativecompressor/CompressorTestData.kt b/jvm-libs/linea/blob-compressor/src/testFixtures/kotlin/net/consensys/linea/nativecompressor/CompressorTestData.kt
index e284425ef..92ffb697a 100644
--- a/jvm-libs/linea/blob-compressor/src/testFixtures/kotlin/net/consensys/linea/nativecompressor/CompressorTestData.kt
+++ b/jvm-libs/linea/blob-compressor/src/testFixtures/kotlin/net/consensys/linea/nativecompressor/CompressorTestData.kt
@@ -1,33 +1,13 @@
package net.consensys.linea.nativecompressor
-import java.nio.ByteBuffer
-import java.nio.ByteOrder
+import linea.rlp.RLP
object CompressorTestData {
- val blocksRlpEncoded: Array = loadTestData()
+ val blocksRlpEncoded: List = RLP.decodeList(readResourcesFile("blocks_rlp.bin"))
- private fun loadTestData(): Array {
- val data = Thread.currentThread().getContextClassLoader().getResourceAsStream("rlp_blocks.bin")!!.readAllBytes()
-
- // first 4 bytes are the number of blocks
- val numBlocks = ByteBuffer.wrap(data, 0, 4).order(ByteOrder.LITTLE_ENDIAN).int
-
- // the rest of the file is the blocks
- // (we repeat them to fill more data)
- val blocks = Array(numBlocks * 2) { ByteArray(0) }
-
- for (j in 0 until 2) {
- var offset = 4
- for (i in 0 until numBlocks) {
- // first 4 bytes are the length of the block
- val blockLen = ByteBuffer.wrap(data, offset, 4).order(ByteOrder.LITTLE_ENDIAN).int
-
- // the rest of the block is the block
- blocks[i + j * numBlocks] = ByteArray(blockLen)
- System.arraycopy(data, offset + 4, blocks[i + j * numBlocks], 0, blockLen)
- offset += 4 + blockLen
- }
- }
- return blocks
+ private fun readResourcesFile(fileName: String): ByteArray {
+ return Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)
+ ?.readAllBytes()
+ ?: throw IllegalArgumentException("File not found in jar resources: file=$fileName")
}
}
diff --git a/jvm-libs/linea/blob-compressor/src/testFixtures/kotlin/net/consensys/linea/nativecompressor/TestDataGeneratorHelper.kt b/jvm-libs/linea/blob-compressor/src/testFixtures/kotlin/net/consensys/linea/nativecompressor/TestDataGeneratorHelper.kt
new file mode 100644
index 000000000..47d9729ce
--- /dev/null
+++ b/jvm-libs/linea/blob-compressor/src/testFixtures/kotlin/net/consensys/linea/nativecompressor/TestDataGeneratorHelper.kt
@@ -0,0 +1,70 @@
+package net.consensys.linea.nativecompressor
+
+import io.vertx.core.json.JsonObject
+import linea.rlp.RLP
+import net.consensys.decodeHex
+import net.consensys.encodeHex
+import net.consensys.linea.testing.filesystem.getPathTo
+import org.hyperledger.besu.ethereum.core.Block
+import java.nio.file.Files
+import java.nio.file.Path
+
+fun loadBlocksFromProverRequests(
+ proverExecutionRequestsFolder: Path
+): List> {
+ val blocks = Files
+ .list(proverExecutionRequestsFolder)
+ .toList()
+ .map { file ->
+ JsonObject(Files.readString(file))
+ .getJsonArray("blocksData")
+ .map { block ->
+ block as JsonObject
+ // block RLP encoded
+ val rlp = block.getString("rlp").decodeHex()
+ RLP.decodeBlockWithMainnetFunctions(rlp) to rlp
+ }
+ }
+ .toList()
+ .flatten()
+ return blocks
+ .sortedBy { it.first.header.number }
+ .also {
+ it.forEach {
+ println("block=${it.first.header} rlp=${it.second.encodeHex()}")
+ }
+ }
+}
+
+fun generateEncodeBlocksToBinaryFromProverRequests(
+ proverExecutionRequestsFolder: Path,
+ outputFilePath: Path
+) {
+ val blocks = loadBlocksFromProverRequests(proverExecutionRequestsFolder)
+ Files.write(outputFilePath, RLP.encodeList(blocks.map { it.second }))
+}
+
+fun loadBlocksRlpEncoded(
+ binFile: Path
+): List {
+ return RLP.decodeList(Files.readAllBytes(binFile))
+}
+
+fun main() {
+ val proverExecutionRequestsDir = getPathTo("tmp/local/prover/v3/execution/requests-done/")
+ val destFile = getPathTo("jvm-libs/linea/blob-compressor/src/testFixtures/resources")
+ .resolve("blocks_rlp.bin")
+
+ generateEncodeBlocksToBinaryFromProverRequests(
+ proverExecutionRequestsDir,
+ destFile
+ )
+
+ // Just a visual indicator that it can read/decode again
+ println("\n\n")
+ loadBlocksRlpEncoded(destFile)
+ .map(RLP::decodeBlockWithMainnetFunctions)
+ .forEach {
+ println("block=$it")
+ }
+}
diff --git a/jvm-libs/linea/blob-compressor/src/testFixtures/resources/blocks_rlp.bin b/jvm-libs/linea/blob-compressor/src/testFixtures/resources/blocks_rlp.bin
new file mode 100644
index 0000000000000000000000000000000000000000..dc13c4de8d66f252b0a5f78c07cd9b25c3fe8498
GIT binary patch
literal 42062
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
literal 0
HcmV?d00001
diff --git a/jvm-libs/linea/blob-compressor/src/testFixtures/resources/rlp_blocks.bin b/jvm-libs/linea/blob-compressor/src/testFixtures/resources/rlp_blocks.bin
deleted file mode 100644
index 82c04c3ff910b96015701321b0da8f673357e801..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 57530
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