From 798de17d8db933a92e31b8b653933efec971592f Mon Sep 17 00:00:00 2001 From: thinkAfCod Date: Wed, 4 Sep 2024 15:22:23 +0800 Subject: [PATCH] remove hildr-batcher and hildr-proposer --- docker/batcher.dock | 14 - docker/proposer.dock | 14 - docker/start-hildr-batcher.sh | 11 - docker/start-hildr-proposer.sh | 13 - hildr-batcher/build.gradle | 273 ---- .../io/optimism/batcher/BatcherSubmitter.java | 94 -- .../io/optimism/batcher/HildrBatcher.java | 26 - .../io/optimism/batcher/channel/Channel.java | 131 -- .../batcher/channel/ChannelConfig.java | 36 - .../batcher/channel/ChannelException.java | 38 - .../batcher/channel/ChannelFullException.java | 38 - .../optimism/batcher/channel/ChannelImpl.java | 388 ----- .../batcher/channel/ChannelManager.java | 267 ---- .../batcher/channel/ReorgException.java | 38 - .../java/io/optimism/batcher/cli/Cli.java | 129 -- .../batcher/compressor/Compressor.java | 49 - .../batcher/compressor/CompressorConfig.java | 32 - .../batcher/compressor/Compressors.java | 32 - .../batcher/compressor/RatioCompressor.java | 121 -- .../exception/CompressorException.java | 20 - .../io/optimism/batcher/config/Config.java | 112 -- .../exception/BatcherExecutionException.java | 38 - .../exception/UnsupportedException.java | 38 - .../batcher/exception/Web3jCallException.java | 38 - .../optimism/batcher/loader/BlockLoader.java | 247 ---- .../batcher/loader/BlockLoaderException.java | 38 - .../optimism/batcher/loader/LoaderConfig.java | 26 - .../batcher/loader/SyncStatusException.java | 38 - .../publisher/ChannelDataPublisher.java | 267 ---- .../publisher/NoDataPublishException.java | 38 - .../batcher/publisher/PublishException.java | 38 - .../batcher/publisher/PublisherConfig.java | 37 - .../batcher/telemetry/BatcherMetrics.java | 109 -- .../telemetry/BatcherMetricsRegistry.java | 31 - .../telemetry/BatcherMetricsServer.java | 57 - .../telemetry/BatcherPrometheusMetrics.java | 277 ---- .../batcher/telemetry/NoopBatcherMetrics.java | 67 - .../optimism/batcher/telemetry/TxMetrics.java | 57 - .../telemetry/TxPrometheusMetrics.java | 105 -- .../io/optimism/type/OpEthSyncStatusRes.java | 113 -- .../io/optimism/type/RollupConfigRes.java | 29 - .../java/io/optimism/type/TxCandidate.java | 13 - hildr-batcher/src/main/resources/logback.xml | 28 - .../io/optimism/batcher/TestConstants.java | 51 - .../compressor/RatioCompressorTest.java | 42 - .../batcher/loader/BlockLoaderTest.java | 118 -- .../publisher/ChannelDataPublisherTest.java | 9 - .../src/test/resources/ch_blocks.json | 1297 ----------------- hildr-proposer/build.gradle | 256 ---- .../io/optimism/proposer/HildrProposer.java | 26 - .../optimism/proposer/L2OutputSubmitter.java | 232 --- .../java/io/optimism/proposer/cli/Cli.java | 125 -- .../io/optimism/proposer/config/Config.java | 30 - .../exception/OutputSubmitterExecution.java | 38 - hildr-proposer/src/main/resources/logback.xml | 28 - settings.gradle | 2 - 56 files changed, 5859 deletions(-) delete mode 100644 docker/batcher.dock delete mode 100644 docker/proposer.dock delete mode 100644 docker/start-hildr-batcher.sh delete mode 100644 docker/start-hildr-proposer.sh delete mode 100644 hildr-batcher/build.gradle delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/BatcherSubmitter.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/HildrBatcher.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/channel/Channel.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelConfig.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelException.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelFullException.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelImpl.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelManager.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/channel/ReorgException.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/cli/Cli.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/compressor/Compressor.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/compressor/CompressorConfig.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/compressor/Compressors.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/compressor/RatioCompressor.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/compressor/exception/CompressorException.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/config/Config.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/exception/BatcherExecutionException.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/exception/UnsupportedException.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/exception/Web3jCallException.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/loader/BlockLoader.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/loader/BlockLoaderException.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/loader/LoaderConfig.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/loader/SyncStatusException.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/publisher/ChannelDataPublisher.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/publisher/NoDataPublishException.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/publisher/PublishException.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/publisher/PublisherConfig.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/telemetry/BatcherMetrics.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/telemetry/BatcherMetricsRegistry.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/telemetry/BatcherMetricsServer.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/telemetry/BatcherPrometheusMetrics.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/telemetry/NoopBatcherMetrics.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/telemetry/TxMetrics.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/batcher/telemetry/TxPrometheusMetrics.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/type/OpEthSyncStatusRes.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/type/RollupConfigRes.java delete mode 100644 hildr-batcher/src/main/java/io/optimism/type/TxCandidate.java delete mode 100644 hildr-batcher/src/main/resources/logback.xml delete mode 100644 hildr-batcher/src/test/java/io/optimism/batcher/TestConstants.java delete mode 100644 hildr-batcher/src/test/java/io/optimism/batcher/compressor/RatioCompressorTest.java delete mode 100644 hildr-batcher/src/test/java/io/optimism/batcher/loader/BlockLoaderTest.java delete mode 100644 hildr-batcher/src/test/java/io/optimism/batcher/publisher/ChannelDataPublisherTest.java delete mode 100644 hildr-batcher/src/test/resources/ch_blocks.json delete mode 100644 hildr-proposer/build.gradle delete mode 100644 hildr-proposer/src/main/java/io/optimism/proposer/HildrProposer.java delete mode 100644 hildr-proposer/src/main/java/io/optimism/proposer/L2OutputSubmitter.java delete mode 100644 hildr-proposer/src/main/java/io/optimism/proposer/cli/Cli.java delete mode 100644 hildr-proposer/src/main/java/io/optimism/proposer/config/Config.java delete mode 100644 hildr-proposer/src/main/java/io/optimism/proposer/exception/OutputSubmitterExecution.java delete mode 100644 hildr-proposer/src/main/resources/logback.xml diff --git a/docker/batcher.dock b/docker/batcher.dock deleted file mode 100644 index 0b58df51..00000000 --- a/docker/batcher.dock +++ /dev/null @@ -1,14 +0,0 @@ -FROM ghcr.io/graalvm/graalvm-community:21 as builder - -WORKDIR /root/hildr -COPY . . -RUN ./gradlew clean hildr-batcher:buildJarForDocker - -FROM ghcr.io/graalvm/graalvm-community:21 - -WORKDIR /usr/local/bin -COPY --from=builder /root/hildr/hildr-batcher/build/docker/hildr-batcher.jar . -ENV HILDR_BATCHER_JAR /usr/local/bin/hildr-batcher.jar -ENV HILDR_BATCHER_MAIN_CLASS io.optimism.batcher.HildrBatcher - -ENTRYPOINT ["java", "--enable-preview", "-cp" , "/usr/local/bin/hildr-batcher.jar", "io.optimism.batcher.HildrBatcher"] \ No newline at end of file diff --git a/docker/proposer.dock b/docker/proposer.dock deleted file mode 100644 index 004e72ab..00000000 --- a/docker/proposer.dock +++ /dev/null @@ -1,14 +0,0 @@ -FROM ghcr.io/graalvm/graalvm-community:21 as builder - -WORKDIR /root/hildr -COPY . . -RUN ./gradlew clean hildr-batcher:buildJarForDocker - -FROM ghcr.io/graalvm/graalvm-community:21 - -WORKDIR /usr/local/bin -COPY --from=builder /root/hildr/hildr-batcher/build/docker/hildr-proposer.jar . -ENV HILDR_PROPOSER_JAR /usr/local/bin/hildr-proposer.jar -ENV HILDR_PROPOSER_MAIN_CLASS io.optimism.proposer.HildrProposer - -ENTRYPOINT ["java", "--enable-preview", "-cp" , "/usr/local/bin/hildr-proposer.jar", "io.optimism.proposer.HildrProposer"] \ No newline at end of file diff --git a/docker/start-hildr-batcher.sh b/docker/start-hildr-batcher.sh deleted file mode 100644 index aa2e1332..00000000 --- a/docker/start-hildr-batcher.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh -set -e - -exec java --enable-preview \ - -cp $HILDR_BATCHER_JAR $HILDR_BATCHER_MAIN_CLASS \ - --l1-rpc-url $L1_RPC_URL \ - --l1-signer $L1_SIGNER \ - --batch-inbox-address $BATCH_INBOX_ADDRESS \ - --l2-rpc-url http://${EXECUTION_CLIENT}:${EXECUTION_CLIENT_RPC_PORT} \ - --rollup-rpc-url http://${ROLLUP_CLIENT}:${ROLLUP_RPC_PORT} \ - --log-level $LOG_LEVEL \ No newline at end of file diff --git a/docker/start-hildr-proposer.sh b/docker/start-hildr-proposer.sh deleted file mode 100644 index 6b2751fb..00000000 --- a/docker/start-hildr-proposer.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -set -e - -exec java --enable-preview \ - -cp $HILDR_PROPOSER_JAR $HILDR_PROPOSER_MAIN_CLASS \ - --l1-rpc-url $L1_RPC_URL \ - --l2-rpc-url http://${EXECUTION_CLIENT}:${EXECUTION_CLIENT_RPC_PORT} \ - --l2-chain-id $L2_CHAIN_ID \ - --l2-signer $L2_SIGNER \ - --l2oo-address $L2OO_ADDRESS \ - --l2dgf-address $L2DGF_ADDRESS \ - --rollup-rpc-url http://${ROLLUP_CLIENT}:${ROLLUP_RPC_PORT} \ - --log-level $LOG_LEVEL \ No newline at end of file diff --git a/hildr-batcher/build.gradle b/hildr-batcher/build.gradle deleted file mode 100644 index 2afd943f..00000000 --- a/hildr-batcher/build.gradle +++ /dev/null @@ -1,273 +0,0 @@ -plugins { - id 'java' - id 'application' - id "jacoco" - id "com.diffplug.spotless" version "6.22.0" - id "net.ltgt.errorprone" version "3.1.0" - id 'com.github.johnrengelman.shadow' version '8.1.1' -} - -group = 'io.optimism' -version = '0.4.4' - -repositories { - // Use Maven Central for resolving dependencies. - mavenCentral() - maven { - url "https://artifacts.consensys.net/public/teku/maven/" - } - maven { - url "https://dl.cloudsmith.io/public/libp2p/jvm-libp2p/maven/" - } - maven { - url "https://hyperledger.jfrog.io/artifactory/besu-maven/" - } - maven { - url "https://artifacts.consensys.net/public/maven/maven/" - } - maven { url "https://artifacts.consensys.net/public/maven/maven/" } - maven { url "https://jitpack.io" } - google() -} - -application { - // Define the main class for the application. - mainClass = 'io.optimism.batcher.HildrBatcher' -} - -tasks.withType(JavaCompile).configureEach { - options.annotationProcessorPath = configurations.annotationProcessor - options.compilerArgs += "--enable-preview" - options.compilerArgs += "-Xlint:preview" -// options.compilerArgs += ["--add-modules", "jdk.incubator.concurrent"] - options.compilerArgs += ["-Aproject=${project.group}/${project.name}"] -} - -tasks.withType(JavaExec).configureEach { - jvmArgs += "--enable-preview" -// jvmArgs += ["--add-modules", "jdk.incubator.concurrent"] -} - -tasks.withType(Test).configureEach { - jvmArgs += "--enable-preview" -// jvmArgs += ["--add-modules", "jdk.incubator.concurrent"] -} - -dependencies { - implementation project(':hildr-utilities') - implementation 'com.github.gestalt-config:gestalt-core:0.29.0' - implementation 'com.github.gestalt-config:gestalt-toml:0.29.0' - - implementation 'com.fasterxml.jackson:jackson-bom:2.15.2' - implementation 'com.fasterxml.jackson.core:jackson-core' - implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-toml' - implementation 'org.jctools:jctools-core:4.0.1' - - implementation 'io.jsonwebtoken:jjwt-api:0.11.5' - implementation 'io.jsonwebtoken:jjwt-impl:0.11.5' - implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5' - - //jsonrpc - implementation('io.vertx:vertx-auth-jwt:4.4.2') - implementation('io.vertx:vertx-core:4.4.2') - implementation('io.vertx:vertx-web:4.4.2') - - implementation 'io.micrometer:micrometer-registry-prometheus:1.11.0' - implementation platform('io.micrometer:micrometer-tracing-bom:1.1.1') - implementation 'io.micrometer:micrometer-tracing' - implementation 'io.micrometer:micrometer-tracing-bridge-otel' - - // Logback - implementation 'ch.qos.logback:logback-core:1.4.12' - implementation 'ch.qos.logback:logback-classic:1.4.14' - implementation 'org.slf4j:slf4j-api:2.0.7' - - implementation platform("io.opentelemetry:opentelemetry-bom-alpha:1.26.0-alpha") - // OpenTelemetry core - implementation(platform("io.opentelemetry:opentelemetry-bom:1.26.0")) - implementation 'io.opentelemetry:opentelemetry-api' - implementation 'io.opentelemetry:opentelemetry-sdk' - implementation 'io.opentelemetry:opentelemetry-sdk-logs' - - // OpenTelemetry log4j appenders - implementation platform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.26.0-alpha") - runtimeOnly 'io.opentelemetry.instrumentation:opentelemetry-logback-mdc-1.0' - - implementation('io.tmio:tuweni-crypto:2.4.2'){ - exclude group: 'org.bouncycastle', module: 'bcprov-jdk15on' - exclude group: 'org.apache.tuweni', module: 'tuweni-bytes' - exclude group: 'org.apache.tuweni', module: 'tuweni-units' - exclude group: 'org.apache.tuweni', module: 'tuweni-rlp' - exclude group: 'org.apache.tuweni', module: 'tuweni-crypto' - } - implementation 'org.bouncycastle:bcprov-jdk18on:1.76' - - implementation 'info.picocli:picocli:4.7.3' - annotationProcessor 'info.picocli:picocli-codegen:4.7.3' - -// implementation fileTree(dir: '../lib', include: '*.jar') - // Use JUnit Jupiter for testing. - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0' - // https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite-api - testImplementation 'org.junit.platform:junit-platform-suite-api:1.9.1' - // https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite-engine - testRuntimeOnly 'org.junit.platform:junit-platform-suite-engine:1.9.1' - - testRuntimeOnly 'org.junit.platform:junit-platform-reporting:1.9.1' - - testImplementation 'org.mockito:mockito-junit-jupiter:2.19.0' - testImplementation("com.squareup.okhttp3:mockwebserver:5.0.0-alpha.14") - - errorprone("com.google.errorprone:error_prone_core:2.18.0") -} - -// Apply a specific Java toolchain to ease working on different environments. -java { - toolchain { - languageVersion = JavaLanguageVersion.of(21) - } -} - -test { - useJUnitPlatform() - testLogging { - events "passed", "skipped", "failed" - } - finalizedBy jacocoTestReport -} - -jacoco { - toolVersion = "0.8.12" -} - -jacocoTestReport { - dependsOn test - - reports { - csv.required = true - } -} - -jacocoTestCoverageVerification { - violationRules { - rule { - limit { - minimum = 0 - } - } - } -} - -spotless { - // optional: limit format enforcement to just the files changed by this feature branch -// ratchetFrom 'origin/main' - - format 'misc', { - // define the files to apply `misc` to - target '*.gradle', '*.md', '.gitignore' - - // define the steps to apply to those files - trimTrailingWhitespace() - indentWithTabs() // or spaces. Takes an integer argument if you don't like 4 - endWithNewline() - } - java { - // Use the default importOrder configuration - - // don't need to set target, it is inferred from java - - // apply a specific flavor of google-java-format - palantirJavaFormat('2.38.0') - // fix formatting of type annotations - formatAnnotations() - - importOrder() - - removeUnusedImports() - } -} - -//checkstyleMain -// .exclude('io/optimism/rpc/handler/TimeoutHandler.java') -// .exclude('io/optimism/rpc/handler/JsonRpcExecutorHandler.java') -// .exclude('io/optimism/rpc/handler/JsonRpcParseHandler.java') -// .exclude('io/optimism/rpc/methods/JsonRpcMethod.java') -// .exclude('io/optimism/rpc/methods/JsonRpcMethodsFactory.java') -// .exclude('io/optimism/rpc/methods/JsonRpcProcessor.java') -// .exclude('io/optimism/rpc/execution/LoggedJsonRpcProcessor.java') -// .exclude('io/optimism/rpc/internal/JsonRpcRequest.java') -// .exclude('io/optimism/rpc/internal/JsonRpcRequestContext.java') -// .exclude('io/optimism/rpc/internal/JsonRpcRequestId.java') -// .exclude('io/optimism/rpc/internal/response/JsonRpcResponse.java') -// .exclude('io/optimism/rpc/internal/response/JsonRpcErrorResponse.java') -// .exclude('io/optimism/rpc/internal/response/JsonRpcError.java') -// .exclude('io/optimism/rpc/internal/response/JsonRpcResponseType.java') -// .exclude('io/optimism/rpc/internal/response/JsonRpcSuccessResponse.java') -// .exclude('io/optimism/rpc/internal/response/JsonRpcNoResponse.java') -// .exclude('io/optimism/rpc/execution/BaseJsonRpcProcessor.java') -// .exclude('io/optimism/rpc/execution/JsonRpcProcessor.java') - -tasks.named('test') { - // Use JUnit Platform for unit tests. - useJUnitPlatform() -} - -check { - dependsOn += jacocoTestCoverageVerification -// dependsOn += integrationTest -} - -tasks.withType(Test).configureEach { - def outputDir = reports.junitXml.outputLocation - jvmArgumentProviders << ({ - [ - "-Djunit.platform.reporting.open.xml.enabled=true", - "-Djunit.platform.reporting.output.dir=${outputDir.get().asFile.absolutePath}", - "--enable-preview", - ] - } as CommandLineArgumentProvider) -} - -java { - withJavadocJar() - withSourcesJar() -} - - -javadoc { - if (JavaVersion.current().isJava9Compatible()) { - options.addBooleanOption('html5', true) - } - options.addBooleanOption('-enable-preview', true) - options.addStringOption('-release', '21') -// options.addStringOption('-add-modules', 'jdk.incubator.concurrent') -} - -jar { - enabled = false - manifest { - attributes "Main-Class": "io.optimism.batcher.HildrBatcher" - attributes "Multi-Release": "true" - } - dependsOn(shadowJar) -} - -shadowJar { - archiveFileName = "${project.name}-${project.version}.jar" -} - -task buildJarForDocker { - dependsOn jar - def buildImageDir = "build/docker" - def out = new ByteArrayOutputStream() - doFirst { - new File(buildImageDir).mkdirs() - copy { - from "build/libs/${project.name}-${project.version}.jar" - into buildImageDir - rename "${project.name}-${project.version}.jar", "${project.name}.jar" - } - } - println(out.toString()) -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/BatcherSubmitter.java b/hildr-batcher/src/main/java/io/optimism/batcher/BatcherSubmitter.java deleted file mode 100644 index f486e576..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/BatcherSubmitter.java +++ /dev/null @@ -1,94 +0,0 @@ -package io.optimism.batcher; - -import com.google.common.util.concurrent.AbstractExecutionThreadService; -import io.optimism.batcher.channel.ChannelConfig; -import io.optimism.batcher.channel.ChannelManager; -import io.optimism.batcher.compressor.CompressorConfig; -import io.optimism.batcher.config.Config; -import io.optimism.batcher.exception.BatcherExecutionException; -import io.optimism.batcher.loader.BlockLoader; -import io.optimism.batcher.loader.LoaderConfig; -import io.optimism.batcher.publisher.ChannelDataPublisher; -import io.optimism.batcher.publisher.PublisherConfig; -import io.optimism.type.BlockId; -import io.optimism.utilities.derive.stages.Frame; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.web3j.protocol.core.methods.response.TransactionReceipt; - -/** - * BatcherSubmitter class. - * - * @author thinkAfCod - * @since 0.1.1 - */ -@SuppressWarnings("UnusedVariable") -public class BatcherSubmitter extends AbstractExecutionThreadService { - - private static final Logger LOGGER = LoggerFactory.getLogger(BatcherSubmitter.class); - - private final Config config; - - private final ChannelManager channelManager; - private final BlockLoader blockLoader; - private final ChannelDataPublisher channelPublisher; - - private volatile boolean isShutdownTriggered = false; - - /** - * Constructor of BatcherSubmitter. - * - * @param config BatcherSubmitter config - */ - public BatcherSubmitter(Config config) { - this.config = config; - this.channelManager = new ChannelManager(ChannelConfig.from(config), CompressorConfig.from(config)); - this.blockLoader = new BlockLoader(LoaderConfig.from(config), this.channelManager::addL2Block); - this.blockLoader.init(); - this.channelPublisher = new ChannelDataPublisher( - PublisherConfig.from(config, this.blockLoader.getRollConfig()), - this.channelManager::txData, - this::handleReceipt); - } - - private void trySubmitBatchData() { - this.blockLoader.loadBlock(); - // If no data has been sent, then sleep for a period of time. - if (!this.channelPublisher.publishPendingBlock()) { - try { - Thread.sleep(config.pollInterval()); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new BatcherExecutionException("Batcher thread has been interrupted", e); - } - } - } - - private void handleReceipt(Frame tx, TransactionReceipt receipt) { - if (receipt.isStatusOK()) { - this.channelManager.txConfirmed(tx, new BlockId(receipt.getBlockHash(), receipt.getBlockNumber())); - } else { - this.channelManager.txFailed(tx); - } - } - - @Override - protected void run() { - while (isRunning() && !this.isShutdownTriggered) { - this.trySubmitBatchData(); - } - } - - @Override - protected void shutDown() throws Exception { - super.shutDown(); - this.blockLoader.close(); - this.channelPublisher.close(); - this.channelManager.clear(); - } - - @Override - protected void triggerShutdown() { - this.isShutdownTriggered = true; - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/HildrBatcher.java b/hildr-batcher/src/main/java/io/optimism/batcher/HildrBatcher.java deleted file mode 100644 index 4b32af6f..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/HildrBatcher.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.optimism.batcher; - -import io.optimism.batcher.cli.Cli; -import picocli.CommandLine; - -/** - * Batcher main method. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class HildrBatcher { - - /** Constructor of HildrBatcher. */ - public HildrBatcher() {} - - /** - * Main method of HildrBatcher. - * - * @param args Starts arguments - */ - public static void main(String[] args) { - int exitCode = new CommandLine(new Cli()).execute(args); - System.exit(exitCode); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/channel/Channel.java b/hildr-batcher/src/main/java/io/optimism/batcher/channel/Channel.java deleted file mode 100644 index 42c5f4e1..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/channel/Channel.java +++ /dev/null @@ -1,131 +0,0 @@ -package io.optimism.batcher.channel; - -import io.optimism.type.BlockId; -import io.optimism.type.L1BlockInfo; -import io.optimism.utilities.derive.stages.Frame; -import java.io.Closeable; -import java.math.BigInteger; -import java.util.List; -import org.web3j.protocol.core.methods.response.EthBlock; - -/** - * Channel interface. cache batch submit data. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public interface Channel extends Closeable { - - /** - * Add block to channel, block will be parsed and be compressed. - * - * @param block Block on L2 - * @return l1 block info - */ - L1BlockInfo addBlock(EthBlock.Block block); - - /** Split channel data to frames. */ - void splitToFrame(); - - /** - * Get next frame data should be published to l1. The data added to the channel will be - * transformed into multiple frames. - * - * @return TxData instance contains frame data - */ - Frame nextFrame(); - - /** - * Push frame to current channel. - * - * @param frame TxData instance - */ - void pushFrame(Frame frame); - - /** - * Get Total frames. - * - * @return total value. - */ - int totalFrames(); - - /** - * Get count of pending frames. - * - * @return count of pending frames - */ - int pendingFrames(); - - /** - * If has frame. - * - * @return true if has data of frame, otherwise false. - */ - boolean hasFrame(); - - /** - * Has none pending tx data. - * - * @return true if has none pending tx data, otherwise false. - */ - boolean noneSubmitted(); - - /** - * Check is tx data fully submitted. - * - * @return ture if fully submitted, otherwise false. - */ - boolean isFullySubmitted(); - - /** - * Process failed tx that belong to the channel. Will push tx back to pending queue. - * - * @param tx failed tx data - */ - void txFailed(Frame tx); - - /** - * Process confirmed tx that belong to the channel. - * - * @param tx confirmed tx data - * @param inclusionBlock tx data be inclusion block number - * @return if channel was timeout, the blocks added to the channel will be returned. - */ - List txConfirmed(Frame tx, BlockId inclusionBlock); - - /** - * If channel touch limit of frame data. - * - * @return true if full of data, otherwise false. - */ - boolean isFull(); - - /** - * If the channel data expired at the specified block height. - * - * @param blockNumber block height number - * @return true if timeout,otherwise false. - */ - boolean isTimeout(BigInteger blockNumber); - - /** - * Update channel data expired at the specified block height. - * - * @param blockNumber block height number - */ - void updateTimeout(final BigInteger blockNumber); - - /** - * Input bytes data. - * - * @return input bytes - */ - int inputBytesLength(); - - /** - * Ready to publishing bytes. - * - * @return ready to publishing bytes - */ - int readyBytesLength(); -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelConfig.java b/hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelConfig.java deleted file mode 100644 index d4114f7d..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelConfig.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.optimism.batcher.channel; - -import io.optimism.batcher.config.Config; -import io.optimism.batcher.telemetry.BatcherMetrics; - -/** - * ChannelConfig class. - * - * @param channelTimeout The maximum number of L1 blocks that the inclusion transactions of a - * channel's frames can span. - * @param maxChannelDuration Timeout of max block number.If 0, duration checks are disabled. - * @param maxFrameSize The maximum byte-size a frame can have. - * @param seqWindowSize The maximum byte-size a frame can have. - * @param subSafetyMargin The maximum byte-size a frame can have. - * @param metrics Batcher metrics - * @author thinkAfCod - * @since 0.1.1 - */ -public record ChannelConfig( - long channelTimeout, - long maxChannelDuration, - int maxFrameSize, - long seqWindowSize, - long subSafetyMargin, - BatcherMetrics metrics) { - - /** - * Create a ChannelConfig instance from Config instance. - * - * @param config Config instance - * @return ChannelConfig instance - */ - public static ChannelConfig from(Config config) { - return new ChannelConfig(30000, 0, 120_000, 3600, 10, config.metrics()); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelException.java b/hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelException.java deleted file mode 100644 index a9b99ed8..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelException.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.optimism.batcher.channel; - -/** - * Batcher Channel Exception class. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class ChannelException extends RuntimeException { - - /** - * Instantiates a new ChannelException. - * - * @param message the message - */ - public ChannelException(String message) { - super(message); - } - - /** - * Instantiates a new ChannelException. - * - * @param message the message - * @param cause the cause - */ - public ChannelException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Instantiates a new ChannelException. - * - * @param cause the cause - */ - public ChannelException(Throwable cause) { - super(cause); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelFullException.java b/hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelFullException.java deleted file mode 100644 index 474ce1dd..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelFullException.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.optimism.batcher.channel; - -/** - * ChannelFullException class. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class ChannelFullException extends ChannelException { - - /** - * Instantiates a new ChannelFullException. - * - * @param message the message - */ - public ChannelFullException(String message) { - super(message); - } - - /** - * Instantiates a new ChannelFullException. - * - * @param message the message - * @param cause the cause - */ - public ChannelFullException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Instantiates a new ChannelFullException. - * - * @param cause the cause - */ - public ChannelFullException(Throwable cause) { - super(cause); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelImpl.java b/hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelImpl.java deleted file mode 100644 index b2b69cf6..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelImpl.java +++ /dev/null @@ -1,388 +0,0 @@ -package io.optimism.batcher.channel; - -import io.optimism.batcher.compressor.Compressor; -import io.optimism.batcher.compressor.exception.CompressorException; -import io.optimism.batcher.exception.UnsupportedException; -import io.optimism.batcher.telemetry.BatcherMetrics; -import io.optimism.type.BlockId; -import io.optimism.type.L1BlockInfo; -import io.optimism.utilities.derive.stages.Frame; -import io.optimism.utilities.derive.stages.SingularBatch; -import io.optimism.utilities.encoding.TxEncoder; -import java.io.IOException; -import java.math.BigInteger; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.web3j.protocol.core.methods.response.EthBlock; -import org.web3j.tuples.generated.Tuple2; -import org.web3j.utils.Numeric; - -/** - * Channel class.Record the batcher data of block transaction and process this data with framing. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class ChannelImpl implements Channel { - - private static final Logger LOGGER = LoggerFactory.getLogger(ChannelImpl.class); - - private static final int MAX_UNSIGNED_SHORT = (1 << 16) - 1; - - private static final String DEPOSIT_TX_TYPE = "0x7E"; - - private static final int CH_ID_LEN = 16; - - private static final int MAX_RLP_BYTES_PER_CHANNEL = 10_000_000; - - private final ChannelConfig chConfig; - - private final BatcherMetrics metrics; - - private final BigInteger seqWindowTimeout; - - private final BigInteger id; - - private final AtomicInteger frameNumber; - - private final List outputFrames; - - private final Map pendingTxs; - - private final Map confirmedTxs; - - private final List blocks; - - private BigInteger timeoutBlock; - - private final Compressor compressor; - - private final AtomicInteger rlpLength; - - private volatile boolean isFull; - - private volatile boolean isClose; - - /** - * Constructor of ChannelImpl. - * - * @param chConfig channel config - * @param compressor block data compressor - */ - public ChannelImpl(ChannelConfig chConfig, Compressor compressor) { - this.chConfig = chConfig; - this.metrics = chConfig.metrics(); - this.seqWindowTimeout = BigInteger.valueOf(chConfig.seqWindowSize() - chConfig.subSafetyMargin()); - this.compressor = compressor; - try { - var chIdBytes = new byte[CH_ID_LEN]; - SecureRandom.getInstanceStrong().nextBytes(chIdBytes); - this.id = Numeric.toBigInt(chIdBytes); - } catch (NoSuchAlgorithmException e) { - throw new UnsupportedException(e); - } - this.blocks = new ArrayList<>(); - this.outputFrames = new ArrayList<>(); - this.pendingTxs = new HashMap<>(); - this.confirmedTxs = new HashMap<>(); - this.rlpLength = new AtomicInteger(); - this.frameNumber = new AtomicInteger(); - this.isFull = false; - this.isClose = false; - } - - @Override - public L1BlockInfo addBlock(final EthBlock.Block block) { - if (this.isFull()) { - throw new ChannelFullException("this channel has been full of block data"); - } - if (this.isClose) { - throw new ChannelException("channel already closed"); - } - final Tuple2 l1InfoAndBatch = this.blockToBatch(block); - final L1BlockInfo l1Info = l1InfoAndBatch.component1(); - final SingularBatch batch = l1InfoAndBatch.component2(); - try { - this.addBatch(batch); - this.blocks.add(block); - } catch (ChannelFullException | CompressorException e) { - this.isFull = true; - } - this.splitToFrame(); - this.updateSeqWindowTimeout(batch); - return l1Info; - } - - @Override - public void splitToFrame() { - if (this.isFull()) { - this.closeAndOutputAllFrames(); - return; - } - this.outputReadyFrames(); - } - - @Override - public Frame nextFrame() { - if (this.outputFrames.isEmpty()) { - throw new ChannelException("not next frame"); - } - var tx = this.outputFrames.removeFirst(); - this.pendingTxs.put(tx.code(), tx); - return tx; - } - - @Override - public void pushFrame(Frame frame) { - if (frame.channelId().equals(this.id)) { - throw new ChannelException("wrong channel"); - } - this.outputFrames.add(frame); - } - - @Override - public int totalFrames() { - return this.frameNumber.get() + 1; - } - - @Override - public int pendingFrames() { - return this.outputFrames.size(); - } - - @Override - public boolean hasFrame() { - return !this.outputFrames.isEmpty(); - } - - @Override - public void txFailed(Frame tx) { - this.metrics.recordBatchTxFailed(); - var code = tx.code(); - if (!this.pendingTxs.containsKey(code)) { - LOGGER.warn("unkown tx marked as failed: chId :{}; frameNum: {}", tx.channelId(), tx.frameNumber()); - return; - } - LOGGER.trace("marked transaction as failed: chId :{}; frameNum: {}", tx.channelId(), tx.frameNumber()); - this.pushFrame(tx); - this.pendingTxs.remove(code); - } - - @Override - public List txConfirmed(Frame tx, BlockId inclusionBlock) { - this.metrics.recordBatchTxSubmitted(); - LOGGER.debug( - "marked tx as confirmed: chId: {}; frameNum: {}; block: {}", - tx.channelId(), - tx.frameNumber(), - inclusionBlock); - var code = tx.code(); - if (!this.pendingTxs.containsKey(code)) { - LOGGER.warn( - "unknown transaction marked as confirmed: chId: {}; frameNum: {}; block: {}", - tx.channelId(), - tx.frameNumber(), - inclusionBlock); - return null; - } - this.pendingTxs.remove(code); - this.confirmedTxs.put(code, inclusionBlock); - var timeout = inclusionBlock - .number() - .add(BigInteger.valueOf(chConfig.channelTimeout())) - .subtract(BigInteger.valueOf(chConfig.subSafetyMargin())); - this.updateTimeout(timeout); - if (this.isTimeout()) { - this.metrics.recordChannelTimedOut(tx); - LOGGER.warn("Channel timeout: chId:{}", tx.channelId()); - return this.blocks; - } - if (this.isFullySubmitted()) { - this.metrics.recordChannelFullySubmitted(tx); - LOGGER.info("Channel is fully submitted: chId:{}", tx.channelId()); - } - return null; - } - - @Override - public boolean isFull() { - return this.isFull; - } - - @Override - public boolean noneSubmitted() { - return this.confirmedTxs.isEmpty() && this.pendingTxs.isEmpty(); - } - - @Override - public boolean isFullySubmitted() { - return this.isFull() && (this.pendingTxs.size() + this.pendingFrames() == 0); - } - - @Override - public boolean isTimeout(BigInteger blockNumber) { - return this.timeoutBlock.equals(blockNumber); - } - - private boolean isTimeout() { - if (this.confirmedTxs.isEmpty()) { - return false; - } - var min = BigInteger.valueOf(Long.MAX_VALUE); - var max = BigInteger.ZERO; - Collection inclusionBlockIds = this.confirmedTxs.values(); - for (BlockId inclusionBlockId : inclusionBlockIds) { - var inclusionBlockNumber = inclusionBlockId.number(); - if (inclusionBlockNumber.compareTo(min) < 0) { - min = inclusionBlockNumber; - } - if (inclusionBlockNumber.compareTo(max) > 0) { - max = inclusionBlockNumber; - } - } - return max.subtract(min).compareTo(BigInteger.valueOf(this.chConfig.channelTimeout())) >= 0; - } - - /** - * update channel data timeout block number. - * - * @param blockNumber block height number - */ - @Override - public void updateTimeout(final BigInteger blockNumber) { - if (this.timeoutBlock == null || this.timeoutBlock.compareTo(blockNumber) > 0) { - this.timeoutBlock = blockNumber; - } - } - - @Override - public int inputBytesLength() { - return this.rlpLength.get(); - } - - @Override - public int readyBytesLength() { - return this.compressor.length(); - } - - @Override - public void close() { - if (this.isClose) { - throw new ChannelException("channel has been closed"); - } - this.isClose = true; - try { - this.compressor.close(); - } catch (IOException e) { - throw new ChannelException("compressor closed failed", e); - } - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - private Tuple2 blockToBatch(EthBlock.Block block) { - final List blockTxs = block.getTransactions(); - if (blockTxs == null || blockTxs.isEmpty()) { - throw new ChannelException(String.format("block %s has no transations", block.getHash())); - } - final EthBlock.TransactionObject depositTxObj = (EthBlock.TransactionObject) blockTxs.getFirst(); - if (!DEPOSIT_TX_TYPE.equalsIgnoreCase(depositTxObj.getType())) { - throw new ChannelException("block txs not contains deposit tx"); - } - - final L1BlockInfo l1Info = L1BlockInfo.from(Numeric.hexStringToByteArray(depositTxObj.getInput())); - - final List txDataList = new ArrayList<>(blockTxs.size()); - for (int i = 1; i < blockTxs.size(); i++) { - final EthBlock.TransactionObject txObj = (EthBlock.TransactionObject) blockTxs.get(i); - if (DEPOSIT_TX_TYPE.equalsIgnoreCase(txObj.getType())) { - continue; - } - txDataList.add(Numeric.toHexString(TxEncoder.encode(txObj))); - } - return new Tuple2( - l1Info, - new SingularBatch( - block.getParentHash(), l1Info.number(), l1Info.blockHash(), block.getTimestamp(), txDataList)); - } - - private int addBatch(SingularBatch batch) { - if (this.isClose) { - throw new ChannelException("channel already closed"); - } - byte[] encode = batch.encode(); - if ((this.rlpLength.get() + encode.length) > MAX_RLP_BYTES_PER_CHANNEL) { - throw new ChannelFullException(String.format( - "could not add %d bytes to channel of %d bytes, max is %d", - encode.length, this.rlpLength.get(), MAX_RLP_BYTES_PER_CHANNEL)); - } - int n = this.compressor.write(encode); - this.rlpLength.addAndGet(encode.length); - return n; - } - - private void closeAndOutputAllFrames() { - this.close(); - boolean isLastFrame = false; - while (!isLastFrame) { - isLastFrame = createFrame(); - } - } - - private void outputReadyFrames() { - while (this.readyBytesLength() >= this.chConfig.maxFrameSize()) { - boolean isLastFrame = this.createFrame(); - if (isLastFrame) { - break; - } - } - } - - private boolean createFrame() { - var frame = this.frame(this.chConfig.maxFrameSize()); - if (frame.frameNumber() == MAX_UNSIGNED_SHORT) { - this.isFull = true; - } - this.outputFrames.add(frame); - // todo numFrames++ - // todo outputBytes += len(frame.data) - return frame.isLastFrame(); - } - - private Frame frame(final int maxSize) { - if (maxSize < Frame.FRAME_V0_OVER_HEAD_SIZE) { - throw new ChannelException("maxSize is too small to fit the fixed frame overhead"); - } - var lastFrameFlag = false; - var dataSize = maxSize - Frame.FRAME_V0_OVER_HEAD_SIZE; - var cprLength = this.compressor.length(); - if (dataSize > cprLength) { - dataSize = cprLength; - lastFrameFlag = this.isClose; - } - - byte[] data = new byte[dataSize]; - int read = this.compressor.read(data); - if (read != data.length) { - read = read == -1 ? 0 : read; - byte[] temp = new byte[read]; - System.arraycopy(data, 0, temp, 0, read); - data = temp; - } - var frame = Frame.create(this.id, this.frameNumber.get(), data, lastFrameFlag); - this.frameNumber.addAndGet(1); - return frame; - } - - private void updateSeqWindowTimeout(final SingularBatch batch) { - var timeout = batch.epochNum().add(this.seqWindowTimeout); - this.updateTimeout(timeout); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelManager.java b/hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelManager.java deleted file mode 100644 index a5674dca..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/channel/ChannelManager.java +++ /dev/null @@ -1,267 +0,0 @@ -package io.optimism.batcher.channel; - -import io.optimism.batcher.compressor.CompressorConfig; -import io.optimism.batcher.compressor.Compressors; -import io.optimism.batcher.telemetry.BatcherMetrics; -import io.optimism.type.BlockId; -import io.optimism.type.L1BlockInfo; -import io.optimism.type.L2BlockRef; -import io.optimism.utilities.derive.stages.Frame; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.web3j.protocol.core.methods.response.EthBlock; - -/** - * ChannelManager class. create and remove channel object. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class ChannelManager { - - private static final Logger LOGGER = LoggerFactory.getLogger(ChannelManager.class); - - private final ChannelConfig chConfig; - - private final BatcherMetrics metrics; - - private final CompressorConfig compressorConfig; - - private List blocks; - - private final List channels; - - private String latestBlockHash; - - private volatile boolean isClosed; - - private Channel latestChannel; - - private Map txChMap; - - /** - * Constructor of ChannelManager. - * - * @param chConfig channel config - * @param compressorConfig compressor config - */ - public ChannelManager(final ChannelConfig chConfig, final CompressorConfig compressorConfig) { - this.chConfig = chConfig; - this.metrics = chConfig.metrics(); - this.compressorConfig = compressorConfig; - this.blocks = new ArrayList<>(256); - this.channels = new ArrayList<>(256); - this.isClosed = false; - this.txChMap = new HashMap<>(); - } - - /** - * Adds an L2 block to the internal blocks queue. It throws ReorgException if the block does not - * extend the last block loaded into the state. If no blocks were added yet, the parent hash check - * is skipped. - * - * @param block L2 block data - */ - public void addL2Block(EthBlock.Block block) { - if (!StringUtils.isEmpty(latestBlockHash) && !latestBlockHash.equals(block.getParentHash())) { - throw new ReorgException("block does not extend existing chain"); - } - this.blocks.add(block); - this.latestBlockHash = block.getHash(); - this.metrics.recordL2BlockInPendingQueue(block); - } - - /** - * Returns the next tx data that should be submitted to L1. - * - *

It currently only uses one frame per transaction. If the pending channel is full, it only - * returns the remaining frames of this channel until it got successfully fully sent to L1. It - * returns io.EOF if there's no pending frame. - * - * @param l1Head l1 head block id - * @return The next tx data that should be submitted to L1. - */ - public Frame txData(final BlockId l1Head) { - Channel framesSource = null; - for (Channel channel : channels) { - if (channel.hasFrame()) { - framesSource = channel; - break; - } - } - if (framesSource != null || this.isClosed) { - return this.nextFrameData(framesSource); - } - // no channel - if (!this.hasSpace(this.latestChannel)) { - this.latestChannel = this.openChannel(); - LOGGER.info( - "Created a channel: id:{}, l1Head: {}, blocksPending:{}", - this.latestChannel, - l1Head, - this.blocks.size()); - this.metrics.recordChannelOpened(null, this.blocks.size()); - } - this.pushBlocks(this.latestChannel); - this.updateChannelTimeout(l1Head); - - return this.nextFrameData(this.latestChannel); - } - - /** - * Records a transaction as failed. It will attempt to resubmit the data in the failed - * transaction. - * - * @param tx channel tx - */ - public void txFailed(final Frame tx) { - var code = tx.code(); - if (!this.txChMap.containsKey(code)) { - LOGGER.warn("transaction from unkown channel marked as failed: id: {}", tx.channelId()); - return; - } - Channel ch = this.txChMap.remove(tx.code()); - ch.txFailed(tx); - if (!this.isClosed || !ch.noneSubmitted()) { - return; - } - LOGGER.info("Channel has no submitted transactions, clearing for shutdown: chId: {}", tx.channelId()); - this.channels.remove(ch); - if (this.latestChannel.equals(ch)) { - this.latestChannel = null; - } - } - - /** - * Marks a transaction as confirmed on L1. Unfortunately even if all frames in a channel have been - * marked as confirmed on L1 the channel may be invalid and need to be resubmitted. This function - * may reset the pending channel if the pending channel has timed out. - * - * @param tx channel tx - * @param inclusionBlock inclusion block id - */ - public void txConfirmed(final Frame tx, final BlockId inclusionBlock) { - this.metrics.recordBatchTxSubmitted(); - LOGGER.debug( - "marked transaction as confirmed: chId: {}; frameNum: {};block: {}", - tx.channelId(), - tx.frameNumber(), - inclusionBlock.number()); - var code = tx.code(); - if (!this.txChMap.containsKey(code)) { - LOGGER.warn( - "transaction from unknown channel marked as confirmed: chId: {}; frameNum: {};block: {}", - tx.channelId(), - tx.frameNumber(), - inclusionBlock.number()); - return; - } - final var ch = this.txChMap.remove(code); - List blocks = ch.txConfirmed(tx, inclusionBlock); - if (blocks != null && !blocks.isEmpty()) { - this.blocks.addAll(blocks); - } - if (!ch.isFullySubmitted()) { - return; - } - this.channels.remove(ch); - if (this.latestChannel.equals(ch)) { - this.latestChannel = null; - } - } - - /** Close channel manager. */ - public void close() { - if (!isClosed) { - this.isClosed = true; - } else { - throw new ChannelException("channel manager has been closed"); - } - } - - /** - * Clears the entire state of the channel manager. It is intended to be used after an L2 reorg. - */ - public void clear() { - LOGGER.trace("clearing channel manager state"); - this.blocks.clear(); - this.isClosed = false; - this.latestChannel = null; - this.channels.clear(); - this.txChMap.clear(); - } - - private Frame nextFrameData(final Channel ch) { - if (ch == null || !ch.hasFrame()) { - return null; - } - var txData = ch.nextFrame(); - this.txChMap.put(txData.code(), ch); - return txData; - } - - private boolean hasSpace(final Channel channel) { - return channel != null && !channel.isFull(); - } - - private Channel openChannel() { - return new ChannelImpl(this.chConfig, Compressors.create(this.compressorConfig)); - } - - private void pushBlocks(final Channel lastChannel) { - int blocksAdded = 0; - L2BlockRef l2Ref = null; - try { - for (final EthBlock.Block block : this.blocks) { - final L1BlockInfo l1Info = lastChannel.addBlock(block); - l2Ref = L2BlockRef.fromBlockAndL1Info(block, l1Info); - if (latestChannel.isFull()) { - break; - } - this.metrics.recordL2BlockInChannel(block); - blocksAdded += 1; - } - } catch (ChannelException e) { - if (!(e instanceof ChannelFullException)) { - LOGGER.error( - "adding block[{}] to channel failed", - this.blocks.get(blocksAdded).getNumber(), - e); - } - } - - if (blocksAdded == this.blocks.size()) { - this.blocks.clear(); - } else { - this.blocks = this.blocks.stream().skip(blocksAdded).collect(Collectors.toList()); - } - - this.metrics.recordL2BlocksAdded( - l2Ref, - blocksAdded, - this.blocks.size(), - this.latestChannel.inputBytesLength(), - this.latestChannel.readyBytesLength()); - - LOGGER.debug( - "Added blocks to channel:" - + " blocksAdded: {}, blocksPending: {}," - + " channelFull: {}, inputBytes: {}, readyBytes: {}", - blocksAdded, - this.blocks.size(), - this.latestChannel.isFull(), - this.latestChannel.inputBytesLength(), - this.latestChannel.readyBytesLength()); - } - - private void updateChannelTimeout(BlockId l1Head) { - this.latestChannel.updateTimeout(l1Head.number().add(BigInteger.valueOf(chConfig.maxChannelDuration()))); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/channel/ReorgException.java b/hildr-batcher/src/main/java/io/optimism/batcher/channel/ReorgException.java deleted file mode 100644 index 9a782daf..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/channel/ReorgException.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.optimism.batcher.channel; - -/** - * ReorgException class. Throws this when chain occurs reorg. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class ReorgException extends RuntimeException { - - /** - * Instantiates a new reorg exception. - * - * @param message the message - */ - public ReorgException(String message) { - super(message); - } - - /** - * Instantiates a new reorg exception. - * - * @param message the message - * @param cause the cause - */ - public ReorgException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Instantiates a new reorg exception. - * - * @param cause the cause - */ - public ReorgException(Throwable cause) { - super(cause); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/cli/Cli.java b/hildr-batcher/src/main/java/io/optimism/batcher/cli/Cli.java deleted file mode 100644 index eb0653e9..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/cli/Cli.java +++ /dev/null @@ -1,129 +0,0 @@ -package io.optimism.batcher.cli; - -import ch.qos.logback.classic.Level; -import io.micrometer.tracing.Tracer; -import io.optimism.batcher.BatcherSubmitter; -import io.optimism.batcher.config.Config; -import io.optimism.batcher.exception.BatcherExecutionException; -import io.optimism.batcher.telemetry.BatcherMetricsServer; -import io.optimism.batcher.telemetry.BatcherPrometheusMetrics; -import io.optimism.cli.typeconverter.LogLevelConverter; -import io.optimism.utilities.telemetry.Logging; -import io.optimism.utilities.telemetry.TracerTaskWrapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import picocli.CommandLine.Command; -import picocli.CommandLine.Option; -import sun.misc.Signal; - -/** - * CLI handler. - * - * @author thinkAfCod - * @since 2023.05 - */ -@Command(name = "hildr", mixinStandardHelpOptions = true, description = "") -public class Cli implements Runnable { - - private static final Logger LOGGER = LoggerFactory.getLogger(Cli.class); - - @Option(names = "--l1-rpc-url", required = true, description = "The L1 chain RPC URL") - String l1RpcUrl; - - @Option(names = "--l2-rpc-url", required = true, description = "The L2 engine RPC URL") - String l2RpcUrl; - - @Option(names = "--rollup-rpc-url", required = true, description = "The rollup node RPC URL") - String rollupRpcUrl; - - @Option(names = "--l1-signer", required = true, description = "The base chain private key") - String l1Signer; - - @Option(names = "--batch-inbox-address", required = true, description = "The address of batch inbox contract") - String batchInboxAddress; - - @Option(names = "--sub-safety-margin", required = true, description = "") - Long subSafetyMargin; - - @Option(names = "--poll-interval", required = true, description = "") - Long pollInterval; - - @Option(names = "--max-l1-tx-size", required = true, description = "") - Long maxL1TxSize; - - @Option(names = "--target-frame-size", required = true, description = "") - Integer targetFrameSize; - - @Option(names = "--target-num-frames", required = true, description = "") - Integer targetNumFrames; - - @Option(names = "--approx-compr-ratio", required = true, description = "") - String approxComprRatio; - - @Option(names = "--enable-metrics", description = "If not contains this option, will not open metrics server") - boolean enableMetrics; - - @Option(names = "--metrics-port", defaultValue = "9200", description = "The port of metrics server ") - Integer metricsPort; - - @Option( - names = "--log-level", - defaultValue = "DEBUG", - converter = LogLevelConverter.class, - description = "Log level") - Level logLevel; - - /** the Cli constructor. */ - public Cli() {} - - @Override - public void run() { - var logger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); - if (logger instanceof ch.qos.logback.classic.Logger) { - var logbackLogger = (ch.qos.logback.classic.Logger) logger; - logbackLogger.setLevel(logLevel); - } - TracerTaskWrapper.setTracerSupplier(Logging.INSTANCE::getTracer); - - // listen close signal - Signal.handle(new Signal("INT"), sig -> System.exit(0)); - Signal.handle(new Signal("TERM"), sig -> System.exit(0)); - - Tracer tracer = Logging.INSTANCE.getTracer("hildr-batcher-cli"); - var span = tracer.nextSpan().name("batcher-submitter").start(); - try (var unused = tracer.withSpan(span)) { - // start metrics server - if (this.enableMetrics) { - BatcherMetricsServer.start(this.metricsPort); - } - // start batcher submitter - BatcherSubmitter submitter = new BatcherSubmitter(this.optionToConfig()); - submitter.startAsync().awaitTerminated(); - } catch (Exception e) { - LOGGER.error("hildr batcher: ", e); - throw new BatcherExecutionException(e); - } finally { - if (this.enableMetrics) { - LOGGER.info("stop metrics"); - BatcherMetricsServer.stop(); - } - span.end(); - } - } - - private Config optionToConfig() { - return new Config( - this.l1RpcUrl, - this.l2RpcUrl, - this.rollupRpcUrl, - this.l1Signer, - this.batchInboxAddress, - this.subSafetyMargin, - this.pollInterval, - this.maxL1TxSize, - this.targetFrameSize, - this.targetNumFrames, - this.approxComprRatio, - new BatcherPrometheusMetrics(BatcherMetricsServer.getRegistry(), "hildr_batcher")); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/compressor/Compressor.java b/hildr-batcher/src/main/java/io/optimism/batcher/compressor/Compressor.java deleted file mode 100644 index 50d719b1..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/compressor/Compressor.java +++ /dev/null @@ -1,49 +0,0 @@ -package io.optimism.batcher.compressor; - -import java.io.Closeable; - -/** - * Tx data bytes compressor interface. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public interface Compressor extends Closeable { - - /** - * write uncompressed data which will be compressed. Should return CompressorFullException if the - * compressor is full and no more data should be written. - * - * @param p uncompressed data - * @return length of compressed data - */ - int write(byte[] p); - - /** - * read compressed data; should only be called after Close. - * - * @param p read buffer bytes to this byte array - * @return length of read compressed data. - */ - int read(byte[] p); - - /** reset all written data. */ - void reset(); - - /** - * returns an estimate of the current length of the compressed data; calling Flush will. increase - * the accuracy at the expense of a poorer compression ratio. - * - * @return an estimate of the current length of the compressed data - */ - int length(); - - /** - * returns CompressorFullException if the compressor is known to be full. Note that calls to Write - * will fail if an error is returned from this method, but calls to Write can still return - * CompressorFullErr even if this does not. - * - * @return return true if compressed data length reached the limit, otherwise return false - */ - boolean isFull(); -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/compressor/CompressorConfig.java b/hildr-batcher/src/main/java/io/optimism/batcher/compressor/CompressorConfig.java deleted file mode 100644 index 8d1b4097..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/compressor/CompressorConfig.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.optimism.batcher.compressor; - -import io.optimism.batcher.config.Config; - -/** - * Compressor Config. - * - * @param targetFrameSize To target when creating channel frames. Note that if the realized - * compression ratio is worse than the approximate, more frames may actually be created. This - * also depends on how close the target is to the max frame size. - * @param targetNumFrames To create in this channel. If the realized compression ratio is worse than - * approxComprRatio, additional leftover frame(s) might get created. - * @param approxComprRatio ApproxComprRatio to assume. Should be slightly smaller than average from - * experiments to avoid the chances of creating a small additional leftover frame. - * @param kind Kind of compressor to use. Must be one of KindKeys. If unset, NewCompressor will - * default to RatioKind. - * @author thinkAfCod - * @since 0.1.1 - */ -public record CompressorConfig(int targetFrameSize, int targetNumFrames, String approxComprRatio, String kind) { - - /** - * Create CompressorConfig instance from Config instance. - * - * @param config Config instance - * @return CompressorConfig instance - */ - public static CompressorConfig from(Config config) { - return new CompressorConfig( - config.targetFrameSize(), config.targetNumFrames(), config.approxComprRatio(), Compressors.RatioKind); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/compressor/Compressors.java b/hildr-batcher/src/main/java/io/optimism/batcher/compressor/Compressors.java deleted file mode 100644 index afee1ae4..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/compressor/Compressors.java +++ /dev/null @@ -1,32 +0,0 @@ -package io.optimism.batcher.compressor; - -import io.optimism.batcher.exception.UnsupportedException; - -/** - * Compressor create tool. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class Compressors { - - /** Kind type of ratio. */ - public static final String RatioKind = "ratio"; - - private Compressors() {} - - /** - * Create Compressor by kind. - * - * @param config Config of compressor - * @return a compressor - */ - public static Compressor create(final CompressorConfig config) { - String kind = config.kind(); - if (kind.equalsIgnoreCase(RatioKind)) { - return new RatioCompressor(config); - } else { - throw new UnsupportedException(String.format("unsupported kind: %s", kind)); - } - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/compressor/RatioCompressor.java b/hildr-batcher/src/main/java/io/optimism/batcher/compressor/RatioCompressor.java deleted file mode 100644 index cea18bd5..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/compressor/RatioCompressor.java +++ /dev/null @@ -1,121 +0,0 @@ -package io.optimism.batcher.compressor; - -import io.optimism.batcher.compressor.exception.CompressorException; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.zip.Deflater; - -/** - * RatioCompressor class. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class RatioCompressor implements Compressor { - - private final CompressorConfig config; - - private final Deflater deflater; - - private final int inputThreshold; - - private final byte[] compressed; - - private volatile ByteArrayOutputStream bos; - - private boolean closed; - - private int pos; - - private int inputLength; - - RatioCompressor(final CompressorConfig config) { - this.config = config; - this.deflater = new Deflater(Deflater.BEST_COMPRESSION); - this.inputThreshold = inputThreshold(); - this.bos = new ByteArrayOutputStream(this.inputThreshold); - this.compressed = new byte[2048]; - this.pos = 0; - this.inputLength = 0; - } - - @Override - public int write(byte[] p) { - if (this.isFull()) { - throw new CompressorException("the target amount of input data has been reached limit"); - } - if (this.isClose()) { - throw new CompressorException("the compressor has been closed"); - } - this.inputLength += p.length; - this.deflater.setInput(p); - int len; - // int compressedLength = 0; - do { - len = this.deflater.deflate(compressed, 0, compressed.length, Deflater.SYNC_FLUSH); - if (len > 0) { - // compressedLength += len; - this.bos.write(compressed, 0, len); - } - } while (len > 0); - this.deflater.reset(); - return p.length; - } - - private boolean isClose() { - return this.closed; - } - - @Override - public int read(byte[] p) { - byte[] data = this.bos.toByteArray(); - int len = this.bos.size(); - if (pos > len) { - return -1; - } - int readLen = p.length; - int avail = len - pos; - if (p.length > avail) { - readLen = avail; - } - System.arraycopy(data, pos, p, 0, readLen); - pos += readLen; - return readLen; - } - - @Override - public void reset() { - if (this.bos != null) { - this.bos.reset(); - } - this.deflater.reset(); - this.pos = 0; - this.inputLength = 0; - } - - @Override - public int length() { - return this.bos.size() - this.pos; - } - - @Override - public boolean isFull() { - return this.inputLength >= this.inputThreshold; - } - - @Override - public void close() throws IOException { - closed = true; - this.deflater.finish(); - this.deflater.end(); - } - - private int inputThreshold() { - return BigDecimal.valueOf(config.targetNumFrames()) - .multiply(BigDecimal.valueOf(config.targetFrameSize())) - .divide(new BigDecimal(config.approxComprRatio()), 2, RoundingMode.HALF_UP) - .intValue(); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/compressor/exception/CompressorException.java b/hildr-batcher/src/main/java/io/optimism/batcher/compressor/exception/CompressorException.java deleted file mode 100644 index dc365559..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/compressor/exception/CompressorException.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.optimism.batcher.compressor.exception; - -/** - * If the compressor is full and no more data should be written or the compressor is known to be - * full. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class CompressorException extends RuntimeException { - - /** - * Constructor of CompressorFullException. - * - * @param message error message - */ - public CompressorException(String message) { - super(message); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/config/Config.java b/hildr-batcher/src/main/java/io/optimism/batcher/config/Config.java deleted file mode 100644 index cc9bd77f..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/config/Config.java +++ /dev/null @@ -1,112 +0,0 @@ -package io.optimism.batcher.config; - -import io.optimism.batcher.telemetry.BatcherMetrics; -import java.util.Objects; - -/** - * Batcher config. - * - * @param l1RpcUrl L1 rpc url - * @param l2RpcUrl L2 rpc url - * @param rollupRpcUrl Op-node rpc url - * @param l1Signer L1 signer private key - * @param batchInboxAddress address of BatchInboxContract on l1 - * @param subSafetyMargin Sub-safety margin - * @param pollInterval Milliseconds of poll interval - * @param maxL1TxSize Max L1 Tx Size - * @param targetFrameSize The target of frame size - * @param targetNumFrames The target of frame number - * @param approxComprRatio Compress ratio - * @param metrics Batcher metrics - * @author thinkAfCod - * @since 0.1.1 - */ -public record Config( - String l1RpcUrl, - String l2RpcUrl, - String rollupRpcUrl, - String l1Signer, - String batchInboxAddress, - Long subSafetyMargin, - Long pollInterval, - Long maxL1TxSize, - Integer targetFrameSize, - Integer targetNumFrames, - String approxComprRatio, - BatcherMetrics metrics) { - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof Config that)) { - return false; - } - return Objects.equals(this.l1RpcUrl, that.l1RpcUrl) - && Objects.equals(this.l2RpcUrl, that.l2RpcUrl) - && Objects.equals(this.rollupRpcUrl, that.rollupRpcUrl) - && Objects.equals(this.l1Signer, that.l1Signer) - && Objects.equals(this.batchInboxAddress, that.batchInboxAddress) - && Objects.equals(this.subSafetyMargin, that.subSafetyMargin) - && Objects.equals(this.pollInterval, that.pollInterval) - && Objects.equals(this.maxL1TxSize, that.maxL1TxSize) - && Objects.equals(this.targetFrameSize, that.targetFrameSize) - && Objects.equals(this.targetNumFrames, that.targetNumFrames) - && Objects.equals(this.approxComprRatio, that.approxComprRatio); - } - - @Override - public int hashCode() { - return Objects.hash( - l1RpcUrl, - l2RpcUrl, - rollupRpcUrl, - l1Signer, - batchInboxAddress, - subSafetyMargin, - pollInterval, - maxL1TxSize, - targetFrameSize, - targetNumFrames, - approxComprRatio); - } - - @Override - public String toString() { - return "Config[" - + "l1RpcUrl=" - + l1RpcUrl - + ", " - + "l2RpcUrl=" - + l2RpcUrl - + ", " - + "rollupRpcUrl=" - + rollupRpcUrl - + ", " - + "l1Signer=" - + l1Signer - + ", " - + "batchInboxAddress=" - + batchInboxAddress - + ", " - + "subSafetyMargin=" - + subSafetyMargin - + ", " - + "pollInterval=" - + pollInterval - + ", " - + "maxL1TxSize=" - + maxL1TxSize - + ", " - + "targetFrameSize=" - + targetFrameSize - + ", " - + "targetNumFrames=" - + targetNumFrames - + ", " - + "approxComprRatio=" - + approxComprRatio - + ']'; - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/exception/BatcherExecutionException.java b/hildr-batcher/src/main/java/io/optimism/batcher/exception/BatcherExecutionException.java deleted file mode 100644 index bb34f9b2..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/exception/BatcherExecutionException.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.optimism.batcher.exception; - -/** - * The bathcer execution exception. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class BatcherExecutionException extends RuntimeException { - - /** - * Instantiates a new Hildr Batcher execution exception. - * - * @param message the message - */ - public BatcherExecutionException(String message) { - super(message); - } - - /** - * Instantiates a new Hildr Batcher execution exception. - * - * @param message the message - * @param cause the cause - */ - public BatcherExecutionException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Instantiates a new Hildr Batcher execution exception. - * - * @param cause the cause - */ - public BatcherExecutionException(Throwable cause) { - super(cause); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/exception/UnsupportedException.java b/hildr-batcher/src/main/java/io/optimism/batcher/exception/UnsupportedException.java deleted file mode 100644 index 1c035c88..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/exception/UnsupportedException.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.optimism.batcher.exception; - -/** - * UnsupportedException class. Throws This when field or operation not supported. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class UnsupportedException extends RuntimeException { - - /** - * Instantiates a new UnsupportedException. - * - * @param message the message - */ - public UnsupportedException(String message) { - super(message); - } - - /** - * Instantiates a new UnsupportedException. - * - * @param message the message - * @param cause the cause - */ - public UnsupportedException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Instantiates a new UnsupportedException. - * - * @param cause the cause - */ - public UnsupportedException(Throwable cause) { - super(cause); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/exception/Web3jCallException.java b/hildr-batcher/src/main/java/io/optimism/batcher/exception/Web3jCallException.java deleted file mode 100644 index b894e70b..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/exception/Web3jCallException.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.optimism.batcher.exception; - -/** - * Web3jCallException class. Throws it when the call of web3j request task failed. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class Web3jCallException extends RuntimeException { - - /** - * Instantiates a new Web3jCallException. - * - * @param message the message - */ - public Web3jCallException(String message) { - super(message); - } - - /** - * Instantiates a new Web3jCallException. - * - * @param message the message - * @param cause the cause - */ - public Web3jCallException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Instantiates a new Web3jCallException. - * - * @param cause the cause - */ - public Web3jCallException(Throwable cause) { - super(cause); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/loader/BlockLoader.java b/hildr-batcher/src/main/java/io/optimism/batcher/loader/BlockLoader.java deleted file mode 100644 index 0f3c898b..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/loader/BlockLoader.java +++ /dev/null @@ -1,247 +0,0 @@ -package io.optimism.batcher.loader; - -import io.optimism.batcher.channel.ReorgException; -import io.optimism.batcher.exception.Web3jCallException; -import io.optimism.batcher.telemetry.BatcherMetrics; -import io.optimism.type.BlockId; -import io.optimism.type.Epoch; -import io.optimism.type.Genesis; -import io.optimism.type.L1BlockInfo; -import io.optimism.type.L1BlockRef; -import io.optimism.type.L2BlockRef; -import io.optimism.type.OpEthSyncStatusRes; -import io.optimism.type.RollupConfigRes; -import io.optimism.type.RollupConfigResult; -import io.optimism.utilities.rpc.Web3jProvider; -import java.io.Closeable; -import java.math.BigInteger; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.StructuredTaskScope; -import java.util.function.Consumer; -import javax.annotation.Nonnull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.web3j.protocol.Web3j; -import org.web3j.protocol.Web3jService; -import org.web3j.protocol.core.DefaultBlockParameter; -import org.web3j.protocol.core.Request; -import org.web3j.protocol.core.methods.response.EthBlock; -import org.web3j.tuples.generated.Tuple2; -import org.web3j.utils.Numeric; - -/** - * BlockLoader class. - * - * @author thinkAfCod - * @since 0.1.1 - */ -@SuppressWarnings("UnusedVariable") -public class BlockLoader implements Closeable { - - private static final Logger LOGGER = LoggerFactory.getLogger(BlockLoader.class); - - private static final String DEPOSIT_TX_TYPE = "0x7E"; - - private static final String OP_ROLLUP_CONFIG = "optimism_rollupConfig"; - - static final String OP_SYNC_STATUS = "optimism_syncStatus"; - - private final Web3j l2Client; - - private final Web3j rollupClient; - - private final Web3jService rollupService; - - private final BatcherMetrics metrics; - - private final Consumer blockConsumer; - - BlockId latestLoadedBlock; - - private RollupConfigResult rollupConfig; - - /** - * Constructor of BlockLoader. - * - * @param config LoaderConfig instance - * @param blockConsumer Consumer block loaded from L2 - */ - public BlockLoader(LoaderConfig config, @Nonnull Consumer blockConsumer) { - this.l2Client = Web3jProvider.createClient(config.l2RpcUrl()); - Tuple2 tuple = Web3jProvider.create(config.rollupUrl()); - this.rollupClient = tuple.component1(); - this.rollupService = tuple.component2(); - this.metrics = config.metrics(); - this.blockConsumer = blockConsumer; - this.latestLoadedBlock = new BlockId("0x0", BigInteger.ZERO); - } - - /** Should be called before load block. */ - public void init() { - if (this.rollupConfig == null) { - this.rollupConfig = this.loadRollConfig(); - } - } - - /** - * Return rollup config object from rollup node. - * - * @return rollup config object - */ - public RollupConfigResult getRollConfig() { - return this.rollupConfig; - } - - /** Trigger load block from L2. */ - public void loadBlock() { - try { - this.loadBlocksIntoState(); - } catch (SyncStatusException e) { - LOGGER.warn("sync status info may not correct", e); - } - } - - @Override - public void close() { - this.l2Client.shutdown(); - this.rollupClient.shutdown(); - } - - void loadBlocksIntoState() { - Tuple2 blockNumbers = this.calculateL2BlockRangeToStore(); - final BigInteger start = blockNumbers.component1().number(); - final BigInteger end = blockNumbers.component2().number(); - var stopBlock = end.add(BigInteger.ONE); - EthBlock.Block lastBlock = null; - for (BigInteger i = start.add(BigInteger.ONE); i.compareTo(stopBlock) < 0; i = i.add(BigInteger.ONE)) { - EthBlock.Block block = this.loadBlockToChannel(i); - this.latestLoadedBlock = BlockId.from(block); - lastBlock = block; - } - if (lastBlock == null) { - throw new BlockLoaderException("get latest block failed"); - } - var l2Ref = l2BlockToBlockRef(lastBlock, getRollConfig().getGenesis()); - this.metrics.recordL2BlocksLoaded(l2Ref); - } - - Tuple2 calculateL2BlockRangeToStore() { - var syncStatus = this.requestSyncStatus(); - if (syncStatus.headL1() == null || syncStatus.headL1().equals(L1BlockRef.emptyBlock)) { - throw new SyncStatusException("empty sync status"); - } - if (latestLoadedBlock.number().equals(BigInteger.ZERO)) { - LOGGER.info("Starting batch-submitter work at L2 safe-head: {}", syncStatus.safeL2()); - latestLoadedBlock = syncStatus.safeL2().toId(); - } else if (latestLoadedBlock.number().compareTo(syncStatus.safeL2().number()) <= 0) { - LOGGER.warn("last submitted block lagged behind L2 safe head: batch submission will continue"); - latestLoadedBlock = syncStatus.safeL2().toId(); - } - - if (syncStatus.safeL2().number().compareTo(syncStatus.unsafeL2().number()) >= 0 - || latestLoadedBlock.number().compareTo(syncStatus.unsafeL2().number()) >= 0) { - throw new SyncStatusException(String.format( - "L2 safe head(%d) ahead of L2 unsafe head(%d)", - syncStatus.safeL2().number(), syncStatus.unsafeL2().number())); - } - return new Tuple2<>(latestLoadedBlock, syncStatus.unsafeL2().toId()); - } - - L2BlockRef l2BlockToBlockRef(final EthBlock.Block block, Genesis genesis) { - Epoch l1Origin; - BigInteger sequenceNumber; - if (block.getNumber().equals(genesis.l2().number())) { - if (!block.getHash().equals(genesis.l2().hash())) { - throw new BlockLoaderException(String.format( - "expected L2 genesis hash to match L2 block at genesis block number %d: %s <> %s", - genesis.l2().number(), block.getHash(), genesis.l2().hash())); - } - l1Origin = genesis.l1(); - sequenceNumber = BigInteger.ZERO; - } else { - var txs = block.getTransactions(); - if (txs == null || txs.isEmpty()) { - throw new BlockLoaderException( - String.format("l2 block is missing L1 info deposit tx, block hash: %s", block.getHash())); - } - EthBlock.TransactionObject tx = - (EthBlock.TransactionObject) txs.getFirst().get(); - if (!DEPOSIT_TX_TYPE.equalsIgnoreCase(tx.getType())) { - throw new BlockLoaderException( - String.format("first payload tx has unexpected tx type: %s", tx.getType())); - } - final byte[] input = Numeric.hexStringToByteArray(tx.getInput()); - L1BlockInfo info = L1BlockInfo.from(input); - l1Origin = info.toEpoch(); - sequenceNumber = info.sequenceNumber(); - } - return new L2BlockRef( - block.getHash(), - block.getNumber(), - block.getParentHash(), - block.getTimestamp(), - l1Origin, - sequenceNumber); - } - - private EthBlock.Block loadBlockToChannel(BigInteger number) { - try { - var block = this.getBlock(number); - blockConsumer.accept(block); - return block; - } catch (ReorgException e) { - this.latestLoadedBlock = null; - throw e; - } - } - - RollupConfigResult loadRollConfig() { - try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { - var future = scope.fork( - () -> new Request<>(OP_ROLLUP_CONFIG, List.of(), this.rollupService, RollupConfigRes.class) - .send() - .getConfig()); - scope.join(); - scope.throwIfFailed(); - return future.get(); - } catch (ExecutionException | InterruptedException e) { - Thread.currentThread().interrupt(); - throw new Web3jCallException("failed to get op-rollup config", e); - } - } - - OpEthSyncStatusRes.OpEthSyncStatus requestSyncStatus() { - final Request req = - new Request<>(OP_SYNC_STATUS, List.of(), this.rollupService, OpEthSyncStatusRes.class); - try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { - var future = scope.fork(req::send); - scope.join(); - scope.throwIfFailed(); - return future.get().getOpEthSyncStatus(); - } catch (ExecutionException e) { - throw new Web3jCallException("StructuredTaskScope execute syncStatus failed:", e); - } catch (InterruptedException e) { - throw new Web3jCallException("Thread has been interrupted while calling calculateL2BlockRangeToStore:", e); - } - } - - EthBlock.Block getBlock(BigInteger blockNumber) { - final Request ethBlockRequest = - l2Client.ethGetBlockByNumber(DefaultBlockParameter.valueOf(blockNumber), true); - EthBlock.Block block; - try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { - var blockFuture = scope.fork(ethBlockRequest::send); - scope.join(); - scope.throwIfFailed(); - block = blockFuture.get().getBlock(); - if (block == null) { - throw new Web3jCallException("failed to get block by number:" + blockNumber); - } - } catch (ExecutionException | InterruptedException e) { - Thread.currentThread().interrupt(); - throw new SyncStatusException("failed to get block by number", e); - } - return block; - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/loader/BlockLoaderException.java b/hildr-batcher/src/main/java/io/optimism/batcher/loader/BlockLoaderException.java deleted file mode 100644 index 56669ffc..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/loader/BlockLoaderException.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.optimism.batcher.loader; - -/** - * BlockLoaderException class. Throws this when occurs error while executing BlockLoader. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class BlockLoaderException extends RuntimeException { - - /** - * Instantiates a new BlockLoaderException. - * - * @param message the message - */ - public BlockLoaderException(String message) { - super(message); - } - - /** - * Instantiates a new BlockLoaderException. - * - * @param message the message - * @param cause the cause - */ - public BlockLoaderException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Instantiates a new BlockLoaderException. - * - * @param cause the cause - */ - public BlockLoaderException(Throwable cause) { - super(cause); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/loader/LoaderConfig.java b/hildr-batcher/src/main/java/io/optimism/batcher/loader/LoaderConfig.java deleted file mode 100644 index 2333fc2d..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/loader/LoaderConfig.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.optimism.batcher.loader; - -import io.optimism.batcher.config.Config; -import io.optimism.batcher.telemetry.BatcherMetrics; - -/** - * L2 loader config. - * - * @param l2RpcUrl L2 rpc url - * @param rollupUrl op-rollup node url - * @param metrics Batcher metrics - * @author thinkAfCod - * @since 0.1.1 - */ -public record LoaderConfig(String l2RpcUrl, String rollupUrl, BatcherMetrics metrics) { - - /** - * Create a LoaderConfig instance from Config instance. - * - * @param config Config instance - * @return LoaderConfig instance - */ - public static LoaderConfig from(Config config) { - return new LoaderConfig(config.l2RpcUrl(), config.rollupRpcUrl(), config.metrics()); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/loader/SyncStatusException.java b/hildr-batcher/src/main/java/io/optimism/batcher/loader/SyncStatusException.java deleted file mode 100644 index a2b7a6ee..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/loader/SyncStatusException.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.optimism.batcher.loader; - -/** - * Sync status exception. Throws this when the call to the SyncStatus API fails. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class SyncStatusException extends RuntimeException { - - /** - * Instantiates a new sync status exception. - * - * @param message the message - */ - public SyncStatusException(String message) { - super(message); - } - - /** - * Instantiates a new sync status exception. - * - * @param message the message - * @param cause the cause - */ - public SyncStatusException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Instantiates a new sync status exception. - * - * @param cause the cause - */ - public SyncStatusException(Throwable cause) { - super(cause); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/publisher/ChannelDataPublisher.java b/hildr-batcher/src/main/java/io/optimism/batcher/publisher/ChannelDataPublisher.java deleted file mode 100644 index ac176659..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/publisher/ChannelDataPublisher.java +++ /dev/null @@ -1,267 +0,0 @@ -package io.optimism.batcher.publisher; - -import io.optimism.batcher.exception.Web3jCallException; -import io.optimism.batcher.telemetry.BatcherMetrics; -import io.optimism.type.BlockId; -import io.optimism.type.L1BlockRef; -import io.optimism.utilities.derive.stages.Frame; -import io.optimism.utilities.gas.GasCalculator; -import io.optimism.utilities.rpc.Web3jProvider; -import io.optimism.utilities.telemetry.TracerTaskWrapper; -import java.io.Closeable; -import java.math.BigInteger; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.StructuredTaskScope; -import java.util.function.BiConsumer; -import java.util.function.Function; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.web3j.crypto.Credentials; -import org.web3j.crypto.RawTransaction; -import org.web3j.protocol.Web3j; -import org.web3j.protocol.core.DefaultBlockParameterName; -import org.web3j.protocol.core.methods.request.Transaction; -import org.web3j.protocol.core.methods.response.EthBlock; -import org.web3j.protocol.core.methods.response.EthEstimateGas; -import org.web3j.protocol.core.methods.response.EthGetTransactionCount; -import org.web3j.protocol.core.methods.response.EthGetTransactionReceipt; -import org.web3j.protocol.core.methods.response.TransactionReceipt; -import org.web3j.tx.RawTransactionManager; -import org.web3j.utils.Numeric; - -/** - * ChannelDataPublisher class. It will get tx data from channelManager and push it to L1. - * - * @author thinkAfCod - * @since 0.1.1 - */ -@SuppressWarnings("UnusedVariable") -public class ChannelDataPublisher implements Closeable { - - private static final Logger LOGGER = LoggerFactory.getLogger(ChannelDataPublisher.class); - - private final PublisherConfig config; - - private final BatcherMetrics metrics; - - private final String fromAddress; - - private final Web3j l1Client; - - private final RawTransactionManager txManager; - - private final Function dataSupplier; - - private final BiConsumer txReceiptReturn; - - private L1BlockRef lastL1Tip; - - private BigInteger nonce; - - /** - * Constructor of ChannelDataPublisher. - * - * @param config publisher config - * @param dataSupplier publisher data supplier - * @param txReceiptReturn tx receipt return callback - */ - public ChannelDataPublisher( - PublisherConfig config, - Function dataSupplier, - BiConsumer txReceiptReturn) { - this.config = config; - this.metrics = config.metrics(); - this.l1Client = Web3jProvider.createClient(config.l1RpcUrl()); - var credentials = Credentials.create(config.l1Signer()); - this.fromAddress = credentials.getAddress(); - this.txManager = new RawTransactionManager( - l1Client, credentials, config.l1chainId().longValue()); - this.dataSupplier = dataSupplier; - this.txReceiptReturn = txReceiptReturn; - } - - /** - * Publish pending block data. - * - * @return return true if there any data has been published, otherwise false. - */ - public boolean publishPendingBlock() { - boolean hasData = false; - boolean sendData = true; - try { - while (sendData) { - sendData = this.publishTxToL1(); - if (!hasData) { - hasData = sendData; - } - } - return hasData; - } catch (NoDataPublishException e) { - LOGGER.info(e.getMessage()); - return hasData; - } - } - - @Override - public void close() { - this.l1Client.shutdown(); - } - - private boolean publishTxToL1() { - final L1BlockRef l1HeadBlockRef = getL1HeadBlockRef(); - this.recordL1Head(l1HeadBlockRef); - var txData = dataSupplier.apply(l1HeadBlockRef.toId()); - if (txData == null) { - LOGGER.trace("no transaction data available"); - throw new NoDataPublishException("no transaction data available"); - } - this.sendTx(txData); - return true; - } - - private void sendTx(final Frame txData) { - final String txBytes = Numeric.toHexString(txData.txBytes()); - final String to = this.config.batchInboxAddress(); - long intrinsicGas = GasCalculator.intrinsicGasWithoutAccessList(txData.txBytes(), false, true, true, false); - - var maxPriorityFeePerGas = this.getMaxPriorityFeePerGas(); - var baseFee = this.getBaseFee(); - var gasFeeCap = GasCalculator.calcGasFeeCap(baseFee, maxPriorityFeePerGas); - var gasLimit = intrinsicGas == 0L - ? this.getEstimateGas(this.config.batchInboxAddress(), txBytes) - : BigInteger.valueOf(intrinsicGas); - - var rawTx = RawTransaction.createTransaction( - this.config.l1chainId().longValue(), - this.nextNonce(), - gasLimit, - to, - BigInteger.ZERO, - txBytes, - maxPriorityFeePerGas, - gasFeeCap); - String txHash = this.signAndSend(rawTx); - var txReceipt = this.getTxReceipt(txHash); - txReceiptReturn.accept(txData, txReceipt.getTransactionReceipt().get()); - } - - private EthGetTransactionReceipt getTxReceipt(final String txHash) { - try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { - var receiptFuture = - scope.fork(() -> l1Client.ethGetTransactionReceipt(txHash).send()); - scope.join(); - scope.throwIfFailed(); - return receiptFuture.get(); - } catch (InterruptedException | ExecutionException e) { - Thread.currentThread().interrupt(); - throw new Web3jCallException("failed to get TxReceipt", e); - } - } - - private L1BlockRef getL1HeadBlockRef() { - try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { - StructuredTaskScope.Subtask headBlockFuture = scope.fork( - TracerTaskWrapper.wrap(() -> l1Client.ethGetBlockByNumber(DefaultBlockParameterName.LATEST, false) - .send() - .getBlock())); - scope.join(); - scope.throwIfFailed(); - var block = headBlockFuture.get(); - if (block == null) { - throw new Web3jCallException("get l1 latest block failed"); - } - return L1BlockRef.from(block); - } catch (ExecutionException | InterruptedException e) { - Thread.currentThread().interrupt(); - throw new Web3jCallException("failed to get L1HeadBlockRef", e); - } - } - - private void recordL1Head(L1BlockRef headRef) { - if (this.lastL1Tip.equals(headRef)) { - return; - } - this.lastL1Tip = headRef; - this.metrics.recordLatestL1Block(headRef); - } - - private synchronized BigInteger nextNonce() { - if (this.nonce != null) { - this.nonce = this.nonce.add(BigInteger.ONE); - return this.nonce; - } - EthGetTransactionCount txCount = null; - try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { - var countFuture = scope.fork(TracerTaskWrapper.wrap(() -> { - var countReq = this.l1Client.ethGetTransactionCount(this.fromAddress, DefaultBlockParameterName.LATEST); - return countReq.send(); - })); - scope.join(); - scope.throwIfFailed(); - txCount = countFuture.get(); - this.nonce = txCount.getTransactionCount(); - return this.nonce; - } catch (InterruptedException | ExecutionException e) { - Thread.currentThread().interrupt(); - throw new Web3jCallException("get tx count failed", e); - } - } - - private BigInteger getMaxPriorityFeePerGas() { - try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { - var gasFuture = scope.fork(TracerTaskWrapper.wrap(() -> { - var countReq = this.l1Client.ethMaxPriorityFeePerGas(); - return countReq.send(); - })); - scope.join(); - scope.throwIfFailed(); - return gasFuture.get().getMaxPriorityFeePerGas(); - } catch (InterruptedException | ExecutionException e) { - Thread.currentThread().interrupt(); - throw new Web3jCallException("get max priority fee gas failed", e); - } - } - - private BigInteger getBaseFee() { - try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { - var gasFuture = scope.fork(TracerTaskWrapper.wrap(() -> { - var headReq = this.l1Client.ethGetBlockByNumber(DefaultBlockParameterName.LATEST, false); - return headReq.send(); - })); - scope.join(); - scope.throwIfFailed(); - return gasFuture.get().getBlock().getBaseFeePerGas(); - } catch (InterruptedException | ExecutionException e) { - Thread.currentThread().interrupt(); - throw new Web3jCallException("get l1 head block failed", e); - } - } - - private BigInteger getEstimateGas(final String to, final String data) { - EthEstimateGas gas = null; - try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { - var gasFuture = scope.fork(TracerTaskWrapper.wrap(() -> { - final Transaction txParam = new Transaction(this.fromAddress, null, null, null, to, null, data); - return this.l1Client.ethEstimateGas(txParam).send(); - })); - scope.join(); - scope.throwIfFailed(); - return gasFuture.get().getAmountUsed(); - } catch (InterruptedException | ExecutionException e) { - Thread.currentThread().interrupt(); - throw new Web3jCallException("get tx count failed", e); - } - } - - private String signAndSend(final RawTransaction rawTx) { - try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { - var txResultFuture = scope.fork(TracerTaskWrapper.wrap(() -> txManager.signAndSend(rawTx))); - scope.join(); - scope.throwIfFailed(); - return txResultFuture.get().getTransactionHash(); - } catch (InterruptedException | ExecutionException e) { - Thread.currentThread().interrupt(); - throw new Web3jCallException("sign and send tx failed", e); - } - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/publisher/NoDataPublishException.java b/hildr-batcher/src/main/java/io/optimism/batcher/publisher/NoDataPublishException.java deleted file mode 100644 index 7cf0d421..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/publisher/NoDataPublishException.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.optimism.batcher.publisher; - -/** - * NoDataPublishException class. Throws this when no available data publish to L1. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class NoDataPublishException extends RuntimeException { - - /** - * Instantiates a new NoDataPublishException. - * - * @param message the message - */ - public NoDataPublishException(String message) { - super(message); - } - - /** - * Instantiates a new NoDataPublishException. - * - * @param message the message - * @param cause the cause - */ - public NoDataPublishException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Instantiates a new NoDataPublishException. - * - * @param cause the cause - */ - public NoDataPublishException(Throwable cause) { - super(cause); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/publisher/PublishException.java b/hildr-batcher/src/main/java/io/optimism/batcher/publisher/PublishException.java deleted file mode 100644 index 30e49b32..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/publisher/PublishException.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.optimism.batcher.publisher; - -/** - * PublishException class. Throws this when publish data to L1. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class PublishException extends RuntimeException { - - /** - * Instantiates a new PublishException. - * - * @param message the message - */ - public PublishException(String message) { - super(message); - } - - /** - * Instantiates a new PublishException. - * - * @param message the message - * @param cause the cause - */ - public PublishException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Instantiates a new PublishException. - * - * @param cause the cause - */ - public PublishException(Throwable cause) { - super(cause); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/publisher/PublisherConfig.java b/hildr-batcher/src/main/java/io/optimism/batcher/publisher/PublisherConfig.java deleted file mode 100644 index cb6ac784..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/publisher/PublisherConfig.java +++ /dev/null @@ -1,37 +0,0 @@ -package io.optimism.batcher.publisher; - -import io.optimism.batcher.config.Config; -import io.optimism.batcher.telemetry.BatcherMetrics; -import io.optimism.type.RollupConfigResult; -import java.math.BigInteger; - -/** - * Publisher Config class. - * - * @param l1RpcUrl L1 rpc url - * @param l1Signer L1 signer private key - * @param l1chainId L1 chain id - * @param batchInboxAddress Address of BatchInboxContract on L1 - * @param metrics Batcher metrics - * @author thinkAfCod - * @since 0.1.1 - */ -public record PublisherConfig( - String l1RpcUrl, String l1Signer, BigInteger l1chainId, String batchInboxAddress, BatcherMetrics metrics) { - - /** - * Create a PublisherConfig instance from Config instance. - * - * @param config Config instance - * @param rollupConfig Rollup config, get from rollup node api - * @return PublisherConfig instance - */ - public static PublisherConfig from(Config config, RollupConfigResult rollupConfig) { - return new PublisherConfig( - config.l1RpcUrl(), - config.l1Signer(), - rollupConfig.getL1ChainId(), - rollupConfig.getBatchInboxAddress(), - config.metrics()); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/BatcherMetrics.java b/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/BatcherMetrics.java deleted file mode 100644 index a1825cc9..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/BatcherMetrics.java +++ /dev/null @@ -1,109 +0,0 @@ -package io.optimism.batcher.telemetry; - -import io.optimism.type.L1BlockRef; -import io.optimism.type.L2BlockRef; -import io.optimism.utilities.derive.stages.Frame; -import org.web3j.protocol.core.methods.response.EthBlock; - -/** - * The batcher metrics interface. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public interface BatcherMetrics { - - /** - * Record latest L1 block ref. - * - * @param l1ref Latest L1 block ref - */ - void recordLatestL1Block(L1BlockRef l1ref); - - /** - * Record L2 block loaded. - * - * @param l2ref L2 block ref - */ - void recordL2BlocksLoaded(L2BlockRef l2ref); - - /** - * Record channel open event. - * - * @param frame Channel frame - * @param numPendingBlocks Number of pending blocks - */ - void recordChannelOpened(Frame frame, int numPendingBlocks); - - /** - * Record L2 block added to channel manager. - * - * @param l2ref L2 block ref - * @param numBlocksAdded Number of added blocks - * @param numPendingBlocks Number of pending blocks - * @param inputBytes Length of channel input bytes - * @param outputComprBytes Length of channel compressed bytes - */ - void recordL2BlocksAdded( - L2BlockRef l2ref, int numBlocksAdded, int numPendingBlocks, int inputBytes, int outputComprBytes); - - /** - * Record L2 block in pending queue. - * - * @param block L2 block - */ - void recordL2BlockInPendingQueue(EthBlock.Block block); - - /** - * Record L2 block put into channel. - * - * @param block L2 block - */ - void recordL2BlockInChannel(EthBlock.Block block); - - /** - * Record channel closed event. - * - * @param frame Channel frame. - * @param numPendingBlocks Number of pending blocks - * @param numFrames Number of channel frames - * @param inputBytes Length of input bytes - * @param outputComprBytes Length of output compressed bytes - * @param errorReason Message of error reason - */ - void recordChannelClosed( - Frame frame, int numPendingBlocks, int numFrames, int inputBytes, int outputComprBytes, String errorReason); - - /** - * Record channel fully submitted event. - * - * @param frame Channel frame - */ - void recordChannelFullySubmitted(Frame frame); - - /** - * Record channel timeout event. - * - * @param frame Channel frame - */ - void recordChannelTimedOut(Frame frame); - - /** Record batch tx submitted event. */ - void recordBatchTxSubmitted(); - - /** Record batch tx success event. */ - void recordBatchTxSuccess(); - - /** Record batch tx failed event. */ - void recordBatchTxFailed(); - - /** - * Record batcher server version. - * - * @param version Batcher server version - */ - void recordInfo(String version); - - /** Record batcher server has been started. */ - void recordUp(); -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/BatcherMetricsRegistry.java b/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/BatcherMetricsRegistry.java deleted file mode 100644 index 87876815..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/BatcherMetricsRegistry.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.optimism.batcher.telemetry; - -import io.micrometer.core.instrument.MeterRegistry; -import io.optimism.utilities.telemetry.MetricsServer; - -/** - * The BatcherMetricsRegistry enum. - * - * @author thinkAfCod - * @since 0.1.1 - */ -@SuppressWarnings("ImmutableEnumChecker") -public enum BatcherMetricsRegistry { - /** The instance of BatcherMetricsRegistry. */ - INSTANCE; - - private final MeterRegistry prometheusRegistry; - - BatcherMetricsRegistry() { - this.prometheusRegistry = MetricsServer.createPrometheusRegistry(); - } - - /** - * Get singleton meter registry. - * - * @return the meter registry - */ - public MeterRegistry registry() { - return this.prometheusRegistry; - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/BatcherMetricsServer.java b/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/BatcherMetricsServer.java deleted file mode 100644 index 03c14a40..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/BatcherMetricsServer.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.optimism.batcher.telemetry; - -import io.micrometer.core.instrument.MeterRegistry; -import io.optimism.utilities.telemetry.MetricsServer; - -/** - * The BatcherMetricsServer type. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class BatcherMetricsServer { - - private BatcherMetricsServer() {} - - /** - * Create a NoopMatcherMetrics instance. - * - * @return NoopMatcherMetrics instance. - */ - public static BatcherMetrics noop() { - return new NoopBatcherMetrics(); - } - - /** - * Start a metrics server on specific port. - * - * @param port Server port - */ - public static void start(int port) { - MeterRegistry registry = getRegistry(); - MetricsServer.start(registry, port); - } - - /** - * Get single instance of the meter register . - * - * @return the meter register - */ - public static MeterRegistry getRegistry() { - return BatcherMetricsRegistry.INSTANCE.registry(); - } - - /** Stop an active metrics server. */ - public static void stop() { - MetricsServer.stop(); - } - - /** - * Check if the service is active. - * - * @return Return ture if MetricsServer has been started and still alive, otherwise false. - */ - public static boolean isActive() { - return MetricsServer.isActive(); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/BatcherPrometheusMetrics.java b/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/BatcherPrometheusMetrics.java deleted file mode 100644 index 74665581..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/BatcherPrometheusMetrics.java +++ /dev/null @@ -1,277 +0,0 @@ -package io.optimism.batcher.telemetry; - -import io.micrometer.core.instrument.Counter; -import io.micrometer.core.instrument.MeterRegistry; -import io.optimism.type.L1BlockRef; -import io.optimism.type.L2BlockRef; -import io.optimism.utilities.derive.stages.Frame; -import io.optimism.utilities.telemetry.MetricsSupplier; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.math.RoundingMode; -import java.time.Instant; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; -import org.apache.commons.lang3.ArrayUtils; -import org.web3j.protocol.core.methods.response.EthBlock; -import org.web3j.rlp.RlpEncoder; -import org.web3j.rlp.RlpString; -import org.web3j.utils.Numeric; - -/** - * The BatcherPrometheusMetrics type. Use this instance to record metrics value - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class BatcherPrometheusMetrics implements BatcherMetrics { - - private static final Map EMPTY_TAGS = new HashMap<>(); - - private static final String LAYER_L1 = "l1"; - - private static final String LAYER_L1_ORIGIN = "l1_origin"; - - private static final String LAYER_L2 = "l2"; - - private static final String LATEST = "latest"; - - private static final String STAGE_LOADED = "loaded"; - - private static final String STAGE_OPENED = "opened"; - - private static final String STAGE_ADDED = "added"; - - private static final String STAGE_CLOSED = "closed"; - - private static final String STAGE_FULLY_SUBMITTED = "fully_submitted"; - - private static final String STAGE_TIMEOUT = "timed_out"; - - private static final String TX_STAGE_SUBMITTED = "submitted"; - - private static final String TX_STAGE_SUCCESS = "success"; - - private static final String TX_STAGE_FAILED = "failed"; - - private static final Map DESC_MAP = new HashMap<>(); - - static { - DESC_MAP.put("refs_number", "Gauge representing the different L1/L2 reference block numbers"); - DESC_MAP.put("refs_time", "Gauge representing the different L1/L2 reference block timestamps"); - DESC_MAP.put( - "refs_hash", "Gauge representing the different L1/L2 reference block hashes truncated to float values"); - DESC_MAP.put( - "refs_latency", - "Gauge representing the different L1/L2 reference block timestamps minus current time," - + " in seconds"); - DESC_MAP.put("refs_seqnr", "Gauge representing the different L2 reference sequence numbers"); - DESC_MAP.put( - "pending_blocks_bytes_total", - "Total size of transactions in pending blocks as they are fetched from L2."); - DESC_MAP.put( - "pending_blocks_bytes_current", - "Current size of transactions in the pending" + " (fetched from L2 but not in a channel) stage."); - - DESC_MAP.put("info", "Tracking version and config info."); - DESC_MAP.put("up", "1 if the op-batcher has finished starting up."); - } - - private final MetricsSupplier metricsSupplier; - - private final HashMap latencySeen; - - private final double[] channelComprRatioBucket; - - /** - * The BatcherPrometheusMetrics constructor. - * - * @param registry The MeterRegistry instance - * @param namespace The prefix of metrics name - */ - public BatcherPrometheusMetrics(MeterRegistry registry, String namespace) { - this.metricsSupplier = new MetricsSupplier(registry, namespace, DESC_MAP); - this.latencySeen = new HashMap<>(); - this.channelComprRatioBucket = - ArrayUtils.addAll(new double[] {0.1, 0.2}, this.metricsSupplier.linearBuckets(0.3, 0.05, 14)); - } - - @Override - public void recordLatestL1Block(L1BlockRef l1ref) { - this.recordRef(LAYER_L1, LATEST, l1ref.number(), l1ref.timestamp(), l1ref.hash()); - } - - @Override - public void recordL2BlocksLoaded(L2BlockRef l2ref) { - this.recordL2Ref(STAGE_LOADED, l2ref); - } - - @Override - public void recordChannelOpened(Frame frame, int numPendingBlocks) { - Map tags = new HashMap<>(); - tags.put("stage", STAGE_OPENED); - this.metricsSupplier.getOrCreateEventMeter("channel", tags).record(); - } - - @Override - public void recordL2BlocksAdded( - L2BlockRef l2ref, int numBlocksAdded, int numPendingBlocks, int inputBytes, int outputComprBytes) { - this.recordL2Ref(STAGE_ADDED, l2ref); - Counter blocksAddedCount = this.metricsSupplier.getOrCreateCounter("blocks_added_count", EMPTY_TAGS); - blocksAddedCount.increment(numBlocksAdded); - Map tags = new HashMap<>(); - tags.put("stage", STAGE_ADDED); - AtomicLong pendingBlocksCount = this.metricsSupplier.getOrCreateGauge("pending_blocks_count", tags); - pendingBlocksCount.getAndSet(numPendingBlocks); - AtomicLong channelInputBytes = this.metricsSupplier.getOrCreateGauge("input_bytes", tags); - channelInputBytes.getAndSet(inputBytes); - AtomicLong channelReadyBytes = this.metricsSupplier.getOrCreateGauge("ready_bytes", EMPTY_TAGS); - channelReadyBytes.getAndSet(outputComprBytes); - } - - @Override - public void recordChannelClosed( - Frame frame, - int numPendingBlocks, - int numFrames, - int inputBytes, - int outputComprBytes, - String errorReason) { - Map tags = new HashMap<>(); - tags.put("stage", STAGE_CLOSED); - this.metricsSupplier.getOrCreateEventMeter("channel", tags).record(); - this.metricsSupplier.getOrCreateGauge("pending_blocks_count", tags).getAndSet(numPendingBlocks); - this.metricsSupplier.getOrCreateGauge("channel_num_frames", EMPTY_TAGS).getAndSet(numFrames); - this.metricsSupplier.getOrCreateGauge("input_bytes", tags).getAndSet(inputBytes); - this.metricsSupplier.getOrCreateGauge("ready_bytes", EMPTY_TAGS).getAndSet(outputComprBytes); - this.metricsSupplier.getOrCreateCounter("input_bytes_total", EMPTY_TAGS).increment(inputBytes); - this.metricsSupplier - .getOrCreateCounter("output_bytes_total", EMPTY_TAGS) - .increment(outputComprBytes); - BigDecimal comprRatio = BigDecimal.ZERO; - if (inputBytes > 0) { - comprRatio = new BigDecimal(outputComprBytes).divide(new BigDecimal(inputBytes), 2, RoundingMode.UP); - } - this.metricsSupplier - .getOrCreateHistogram("channel_compr_ratio", null, this.channelComprRatioBucket, EMPTY_TAGS) - .record(comprRatio.doubleValue()); - } - - @Override - public void recordL2BlockInPendingQueue(EthBlock.Block block) { - var size = estimateBatchSize(block); - this.metricsSupplier - .getOrCreateCounter("pending_blocks_bytes_total", EMPTY_TAGS) - .increment((double) size); - this.metricsSupplier - .getOrCreateCounter("pending_blocks_bytes_current", EMPTY_TAGS) - .increment((double) size); - } - - @Override - public void recordL2BlockInChannel(EthBlock.Block block) { - var size = estimateBatchSize(block); - this.metricsSupplier - .getOrCreateCounter("pending_blocks_bytes_current", EMPTY_TAGS) - .increment((double) -1 * size); - } - - @Override - public void recordChannelFullySubmitted(Frame frame) { - Map tags = new HashMap<>(); - tags.put("stage", STAGE_FULLY_SUBMITTED); - this.metricsSupplier.getOrCreateEventMeter("channel", tags).record(); - } - - @Override - public void recordChannelTimedOut(Frame frame) { - Map tags = new HashMap<>(); - tags.put("stage", STAGE_TIMEOUT); - this.metricsSupplier.getOrCreateEventMeter("channel", tags).record(); - } - - @Override - public void recordBatchTxSubmitted() { - Map tags = new HashMap<>(); - tags.put("stage", TX_STAGE_SUBMITTED); - this.metricsSupplier.getOrCreateEventMeter("batcher_tx", tags).record(); - } - - @Override - public void recordBatchTxSuccess() { - Map tags = new HashMap<>(); - tags.put("stage", TX_STAGE_SUCCESS); - this.metricsSupplier.getOrCreateEventMeter("batcher_tx", tags).record(); - } - - @Override - public void recordBatchTxFailed() { - Map tags = new HashMap<>(); - tags.put("stage", TX_STAGE_FAILED); - this.metricsSupplier.getOrCreateEventMeter("batcher_tx", tags).record(); - } - - @Override - public void recordInfo(String version) { - Map tags = new HashMap<>(); - tags.put("version", version); - this.metricsSupplier.getOrCreateGauge("info", tags).getAndSet(1); - } - - @Override - public void recordUp() { - this.metricsSupplier.getOrCreateGauge("up", EMPTY_TAGS).getAndSet(1); - } - - private void recordL2Ref(String stage, L2BlockRef l2ref) { - this.recordRef(LAYER_L2, stage, l2ref.number(), l2ref.timestamp(), l2ref.hash()); - - this.recordRef( - LAYER_L1_ORIGIN, - stage, - l2ref.l1origin().number(), - BigInteger.ZERO, - l2ref.l1origin().hash()); - - Map tags = new HashMap<>(); - tags.put("stage", stage); - AtomicLong seqNr = this.metricsSupplier.getOrCreateGauge("refs_seqnr", tags); - seqNr.getAndSet(l2ref.sequenceNumber().longValue()); - } - - private void recordRef(String layer, String type, BigInteger number, BigInteger timestamp, String hash) { - final Map tags = new HashMap<>(); - tags.put("layer", layer); - tags.put("type", type); - AtomicLong refsNumber = this.metricsSupplier.getOrCreateGauge("refs_number", tags); - refsNumber.getAndSet(number.longValue()); - if (timestamp != null && !timestamp.equals(BigInteger.ZERO)) { - AtomicLong refsTime = this.metricsSupplier.getOrCreateGauge("refs_time", tags); - refsTime.getAndSet(timestamp.longValue()); - if (!hash.equals(this.latencySeen.get(LATEST))) { - this.latencySeen.put(LATEST, hash); - AtomicLong letencySeen = this.metricsSupplier.getOrCreateGauge("refs_latency", tags); - letencySeen.getAndSet(timestamp.longValue() - Instant.now().toEpochMilli()); - } - } - AtomicLong hashGuage = this.metricsSupplier.getOrCreateGauge("refs_hash", tags); - hashGuage.getAndSet(Numeric.toBigInt(hash).longValue()); - } - - @SuppressWarnings("rawtypes") - private long estimateBatchSize(EthBlock.Block block) { - int size = 70; - var txs = block.getTransactions(); - for (EthBlock.TransactionResult tx : txs) { - var txObj = (EthBlock.TransactionObject) tx; - if (txObj.getType().equalsIgnoreCase("0x7E")) { - continue; - } - String input = txObj.getInput(); - byte[] encode = RlpEncoder.encode(RlpString.create(input)); - size += encode.length + 2; - } - return size; - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/NoopBatcherMetrics.java b/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/NoopBatcherMetrics.java deleted file mode 100644 index cb9f45f7..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/NoopBatcherMetrics.java +++ /dev/null @@ -1,67 +0,0 @@ -package io.optimism.batcher.telemetry; - -import io.optimism.type.L1BlockRef; -import io.optimism.type.L2BlockRef; -import io.optimism.utilities.derive.stages.Frame; -import org.web3j.protocol.core.methods.response.EthBlock; - -/** - * An empty metrics when not enable open a metrics. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class NoopBatcherMetrics implements BatcherMetrics { - - /** The NoopBatcherMetrics constructor. */ - public NoopBatcherMetrics() {} - - @Override - public void recordLatestL1Block(L1BlockRef l1ref) {} - - @Override - public void recordL2BlocksLoaded(L2BlockRef l2ref) {} - - @Override - public void recordChannelOpened(Frame frame, int numPendingBlocks) {} - - @Override - public void recordL2BlocksAdded( - L2BlockRef l2ref, int numBlocksAdded, int numPendingBlocks, int inputBytes, int outputComprBytes) {} - - @Override - public void recordL2BlockInPendingQueue(EthBlock.Block block) {} - - @Override - public void recordL2BlockInChannel(EthBlock.Block block) {} - - @Override - public void recordChannelClosed( - Frame frame, - int numPendingBlocks, - int numFrames, - int inputBytes, - int outputComprBytes, - String errorReason) {} - - @Override - public void recordChannelFullySubmitted(Frame frame) {} - - @Override - public void recordChannelTimedOut(Frame frame) {} - - @Override - public void recordBatchTxSubmitted() {} - - @Override - public void recordBatchTxSuccess() {} - - @Override - public void recordBatchTxFailed() {} - - @Override - public void recordInfo(String version) {} - - @Override - public void recordUp() {} -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/TxMetrics.java b/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/TxMetrics.java deleted file mode 100644 index a7690aef..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/TxMetrics.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.optimism.batcher.telemetry; - -import java.math.BigInteger; -import org.web3j.protocol.core.methods.response.TransactionReceipt; - -/** - * Metrics of transaction. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public interface TxMetrics { - /** - * Record current nonce. - * - * @param nonce The current nonce - */ - void recordNonce(BigInteger nonce); - - /** - * Record pending tx count. - * - * @param pending The pending tx count - */ - void recordPendingTx(long pending); - - /** - * Record tx confirmed fee. - * - * @param receipt The tx receipt - */ - void txConfirmed(TransactionReceipt receipt); - - /** - * Record gas bump count. - * - * @param times The times of gas bump count - */ - void recordGasBumpCount(int times); - - /** - * Record tx confirmation latency. - * - * @param latency The tx confirmation latency - */ - void recordTxConfirmationLatency(long latency); - - /** - * Record tx published event. If reason not empty, will increase error count - * - * @param reason Error reason - */ - void txPublished(String reason); - - /** Record rpc error count. */ - void rpcError(); -} diff --git a/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/TxPrometheusMetrics.java b/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/TxPrometheusMetrics.java deleted file mode 100644 index d01eaa73..00000000 --- a/hildr-batcher/src/main/java/io/optimism/batcher/telemetry/TxPrometheusMetrics.java +++ /dev/null @@ -1,105 +0,0 @@ -package io.optimism.batcher.telemetry; - -import io.micrometer.core.instrument.MeterRegistry; -import io.optimism.utilities.telemetry.MetricsSupplier; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.math.RoundingMode; -import java.util.HashMap; -import java.util.Map; -import org.apache.commons.lang3.StringUtils; -import org.web3j.protocol.core.methods.response.TransactionReceipt; -import org.web3j.utils.Convert; -import org.web3j.utils.Numeric; - -/** - * The type of TxPrometheusMetrics. It would record metrics to prometheus metrics. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class TxPrometheusMetrics implements TxMetrics { - - private static final Map EMPTY_TAGS = new HashMap<>(); - - private static final Map DESC_MAP = new HashMap<>(); - - private static final double[] FEE_GWEI_BUCKETS = - new double[] {0.5, 1, 2, 5, 10, 20, 40, 60, 80, 100, 200, 400, 800, 1600}; - - static { - DESC_MAP.put("tx_fee_gwei", "L1 gas fee for transactions in GWEI."); - DESC_MAP.put("tx_fee_gwei_total", "Sum of fees spent for all transactions in GWEI."); - DESC_MAP.put("tx_fee_histogram_gwei", "Tx Fee in GWEI."); - DESC_MAP.put("tx_gas_bump", "Number of times a transaction gas needed to be bumped before it got included."); - DESC_MAP.put("tx_confirmed_latency_ms", "Latency of a confirmed transaction in milliseconds."); - DESC_MAP.put("current_nonce", "Current nonce of the from address."); - DESC_MAP.put("pending_txs", "Number of transactions pending receipts."); - DESC_MAP.put("tx_publish_error_count", "Count of publish errors. Labels are sanitized error strings."); - DESC_MAP.put("rpc_error_count", "Temporary: Count of RPC errors (like timeouts) that have occurred."); - } - - private final MetricsSupplier metricsSupplier; - - /** - * The TxPrometheusMetrics constructor. - * - * @param registry The meter registry instance. - * @param namespace The prefix of metrics name. - */ - public TxPrometheusMetrics(MeterRegistry registry, String namespace) { - this.metricsSupplier = new MetricsSupplier(registry, namespace + "_tx", DESC_MAP); - } - - @Override - public void recordNonce(BigInteger nonce) { - this.metricsSupplier.getOrCreateGauge("current_nonce", EMPTY_TAGS).getAndSet(nonce.longValue()); - } - - @Override - public void recordPendingTx(long pending) { - this.metricsSupplier.getOrCreateGauge("pending_txs", EMPTY_TAGS).getAndSet(pending); - } - - @Override - public void txConfirmed(TransactionReceipt receipt) { - var effectiveGasPrice = new BigDecimal(Numeric.toBigInt(receipt.getEffectiveGasPrice())); - var gasUsed = new BigDecimal(receipt.getGasUsed()); - BigDecimal fee = Convert.fromWei(effectiveGasPrice.divide(gasUsed, 2, RoundingMode.UP), Convert.Unit.GWEI); - this.metricsSupplier.getOrCreateGaugeDecimal("tx_fee_gwei", EMPTY_TAGS).getAndSet(fee); - this.metricsSupplier.getOrCreateCounter("tx_fee_gwei_total", EMPTY_TAGS).increment(fee.doubleValue()); - this.metricsSupplier - .getOrCreateHistogram("tx_fee_histogram_gwei", "GWEI", FEE_GWEI_BUCKETS, EMPTY_TAGS) - .record(fee.doubleValue()); - } - - @Override - public void recordGasBumpCount(int times) { - this.metricsSupplier.getOrCreateGauge("tx_gas_bump", EMPTY_TAGS).getAndSet(times); - } - - @Override - public void recordTxConfirmationLatency(long latency) { - this.metricsSupplier - .getOrCreateGauge("tx_confirmed_latency_ms", EMPTY_TAGS) - .getAndSet(latency); - } - - @Override - public void txPublished(String reason) { - if (StringUtils.isEmpty(reason)) { - HashMap tags = new HashMap<>(); - tags.put("error", reason); - this.metricsSupplier - .getOrCreateCounter("tx_publish_error_count", tags) - .increment(1); - } else { - this.metricsSupplier.getOrCreateEventMeter("publish", EMPTY_TAGS).record(); - } - } - - @Override - public void rpcError() { - this.metricsSupplier.getOrCreateCounter("rpc_error_count", EMPTY_TAGS).increment(); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/type/OpEthSyncStatusRes.java b/hildr-batcher/src/main/java/io/optimism/type/OpEthSyncStatusRes.java deleted file mode 100644 index d53dc600..00000000 --- a/hildr-batcher/src/main/java/io/optimism/type/OpEthSyncStatusRes.java +++ /dev/null @@ -1,113 +0,0 @@ -package io.optimism.type; - -import java.util.Objects; -import org.web3j.protocol.core.Response; - -/** - * Response for the Optimism Node SyncStatus API. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class OpEthSyncStatusRes extends Response { - - /** Constructor of OpEthSyncStatusRes. */ - public OpEthSyncStatusRes() {} - - @Override - public void setResult(OpEthSyncStatusRes.OpEthSyncStatus result) { - super.setResult(result); - } - - /** - * Returns OpEthSyncStatus data. - * - * @return OpEthSyncStatus data - */ - public OpEthSyncStatus getOpEthSyncStatus() { - return getResult(); - } - - /** - * OpEthSyncStatus record class. - * - * @param currentL1 The L1 block that the derivation process is currently at in the inner-most - * stage. This may not be fully derived into L2 data yet. The safe L2 blocks were - * produced/included fully from the L1 chain up to and including this L1 block. If the node is - * synced, this matches the HeadL1, minus the verifier confirmation distance. - * @param currentL1Finalized The L1 block that the derivation process is currently accepting as - * finalized. in the inner-most stage, This may not be fully derived into L2 data yet. The - * finalized L2 blocks were produced/included fully from the L1 chain up to and including this - * L1 block. This may lag behind the FinalizedL1 when the FinalizedL1 could not yet be - * verified to be canonical w.r.t. the currently derived L2 chain. It may be zeroed if no - * block could be verified yet. - * @param headL1 HeadL1 is the perceived head of the L1 chain, no confirmation distance. The head - * is not guaranteed to build on the other L1 sync status fields, as the node may be in - * progress of resetting to adapt to a L1 reorg. - * @param safeL1 SafeL1 points to the L1 block. - * @param finalizedL1 Already finalized L1 block. - * @param unsafeL2 UnsafeL2 is the absolute tip of the L2 chain, pointing to block data that has - * not been submitted to L1 yet. The sequencer is building this, and verifiers may also be - * ahead of the SafeL2 block if they sync blocks via p2p or other offchain sources. - * @param safeL2 SafeL2 points to the L2 block that was derived from the L1 chain. This point may - * still reorg if the L1 chain reorgs. - * @param finalizedL2 FinalizedL2 points to the L2 block that was derived fully from finalized L1 - * information, thus irreversible. - * @param queuedUnsafeL2 UnsafeL2SyncTarget points to the first unprocessed unsafe L2 block. It - * may be zeroed if there is no targeted block. - */ - public record OpEthSyncStatus( - L1BlockRef currentL1, - L1BlockRef currentL1Finalized, - L1BlockRef headL1, - L1BlockRef safeL1, - L1BlockRef finalizedL1, - L2BlockRef unsafeL2, - L2BlockRef safeL2, - L2BlockRef finalizedL2, - L2BlockRef queuedUnsafeL2) { - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof OpEthSyncStatus that)) return false; - return Objects.equals(currentL1, that.currentL1) - && Objects.equals(currentL1Finalized, that.currentL1Finalized) - && Objects.equals(headL1, that.headL1) - && Objects.equals(safeL1, that.safeL1) - && Objects.equals(finalizedL1, that.finalizedL1) - && Objects.equals(unsafeL2, that.unsafeL2) - && Objects.equals(safeL2, that.safeL2) - && Objects.equals(finalizedL2, that.finalizedL2) - && Objects.equals(queuedUnsafeL2, that.queuedUnsafeL2); - } - - @Override - public int hashCode() { - return Objects.hash( - currentL1, - currentL1Finalized, - headL1, - safeL1, - finalizedL1, - unsafeL2, - safeL2, - finalizedL2, - queuedUnsafeL2); - } - - @Override - public String toString() { - return "OpEthSyncStatus{" + "currentL1=" - + currentL1 + ", currentL1Finalized=" - + currentL1Finalized + ", headL1=" - + headL1 + ", safeL1=" - + safeL1 + ", finalizedL1=" - + finalizedL1 + ", unsafeL2=" - + unsafeL2 + ", safeL2=" - + safeL2 + ", finalizedL2=" - + finalizedL2 + ", queuedUnsafeL2=" - + queuedUnsafeL2 + '}'; - } - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/type/RollupConfigRes.java b/hildr-batcher/src/main/java/io/optimism/type/RollupConfigRes.java deleted file mode 100644 index a4286445..00000000 --- a/hildr-batcher/src/main/java/io/optimism/type/RollupConfigRes.java +++ /dev/null @@ -1,29 +0,0 @@ -package io.optimism.type; - -import org.web3j.protocol.core.Response; - -/** - * RollupConfig Response. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class RollupConfigRes extends Response { - - /** Constructor of RollupConfigRes. */ - public RollupConfigRes() {} - - /** - * Returns RollupConfig. - * - * @return rollup config info - */ - public RollupConfigResult getConfig() { - return getResult(); - } - - @Override - public void setResult(RollupConfigResult result) { - super.setResult(result); - } -} diff --git a/hildr-batcher/src/main/java/io/optimism/type/TxCandidate.java b/hildr-batcher/src/main/java/io/optimism/type/TxCandidate.java deleted file mode 100644 index 074d71a5..00000000 --- a/hildr-batcher/src/main/java/io/optimism/type/TxCandidate.java +++ /dev/null @@ -1,13 +0,0 @@ -package io.optimism.type; - -/** - * TxCandidate is a transaction candidate that can be submitted to ask to construct a transaction - * with gas price bounds. - * - * @param txData the transaction data to be used in the constructed tx. - * @param address To is the recipient of the constructed tx. Nil means contract creation. - * @param gasLimit the gas limit to be used in the constructed tx. - * @author thinkAfCod - * @since 0.1.1 - */ -public record TxCandidate(byte[] txData, String address, long gasLimit) {} diff --git a/hildr-batcher/src/main/resources/logback.xml b/hildr-batcher/src/main/resources/logback.xml deleted file mode 100644 index 0e2c6a65..00000000 --- a/hildr-batcher/src/main/resources/logback.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} trace_id=%X{trace_id} span_id=%X{span_id} trace_flags=%X{trace_flags} %msg%n - - - - - logs/app.log - - app-%d{yyyy-MM-dd HH}.gz - 30 - 3GB - - - %d{HH:mm:ss.SSS} %-5level %logger{36} trace_id=%X{trace_id} span_id=%X{span_id} trace_flags=%X{trace_flags} %msg%n - - - - - - - - - - - diff --git a/hildr-batcher/src/test/java/io/optimism/batcher/TestConstants.java b/hildr-batcher/src/test/java/io/optimism/batcher/TestConstants.java deleted file mode 100644 index 2400d444..00000000 --- a/hildr-batcher/src/test/java/io/optimism/batcher/TestConstants.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.optimism.batcher; - -import java.util.Map; -import org.apache.commons.lang3.StringUtils; - -/** - * The type Test constants. - * - * @author thinkAfCod - * @since 2023.06 - */ -public class TestConstants { - - /** The constant isConfiguredApiKeyEnv. */ - public static boolean isConfiguredApiKeyEnv = false; - - private static final String ETH_API_ENV = "ETH_API_KEY"; - private static final String OPT_API_ENV = "OPT_API_KEY"; - private static final String ROLLUP_API_KEY = "ROLLUP_API_KEY"; - - /** The L 1 rpc url format. */ - static String l1RpcUrlFormat = "https://eth-goerli.g.alchemy.com/v2/%s"; - - /** The L 2 rpc url format. */ - static String l2RpcUrlFormat = "https://opt-goerli.g.alchemy.com/v2/%s"; - - public static String l1RpcUrl; - - public static String l2RpcUrl; - - public static String rollupRpcUrl; - - static { - Map envs = System.getenv(); - String ethApiKey = envs.get(ETH_API_ENV); - String optApiKey = envs.get(OPT_API_ENV); - String rollUpApiUrl = envs.get(ROLLUP_API_KEY); - - if (!StringUtils.isEmpty(ethApiKey)) { - l1RpcUrl = l1RpcUrlFormat.formatted(ethApiKey); - } - if (!StringUtils.isEmpty(optApiKey)) { - l2RpcUrl = l2RpcUrlFormat.formatted(optApiKey); - } - if (!StringUtils.isEmpty(rollUpApiUrl)) { - rollupRpcUrl = rollUpApiUrl; - } - } - - private TestConstants() {} -} diff --git a/hildr-batcher/src/test/java/io/optimism/batcher/compressor/RatioCompressorTest.java b/hildr-batcher/src/test/java/io/optimism/batcher/compressor/RatioCompressorTest.java deleted file mode 100644 index 19d00f70..00000000 --- a/hildr-batcher/src/test/java/io/optimism/batcher/compressor/RatioCompressorTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package io.optimism.batcher.compressor; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.zip.DataFormatException; -import java.util.zip.Inflater; -import org.junit.jupiter.api.Test; - -/** - * Ratio compressor test case. - * - * @author thinkAfCod - * @since 0.1.1 - */ -class RatioCompressorTest { - - @Test - public void testCompressor() throws DataFormatException, IOException { - var cprsConfig = new CompressorConfig(10_000, 1, "0.4", Compressors.RatioKind); - var cprr = new RatioCompressor(cprsConfig); - - final String source = "test compressor data 123456789987654321"; - byte[] sourceBytes = source.getBytes(StandardCharsets.UTF_8); - cprr.write(sourceBytes); - byte[] tmp = new byte[100]; - int n = cprr.read(tmp); - cprr.close(); - - Inflater inflater = new Inflater(); - inflater.setInput(Arrays.copyOf(tmp, n)); - - byte[] uncompressed = new byte[sourceBytes.length]; - inflater.inflate(uncompressed); - inflater.finished(); - inflater.end(); - - assertEquals(source, new String(uncompressed, StandardCharsets.UTF_8)); - } -} diff --git a/hildr-batcher/src/test/java/io/optimism/batcher/loader/BlockLoaderTest.java b/hildr-batcher/src/test/java/io/optimism/batcher/loader/BlockLoaderTest.java deleted file mode 100644 index ca43813d..00000000 --- a/hildr-batcher/src/test/java/io/optimism/batcher/loader/BlockLoaderTest.java +++ /dev/null @@ -1,118 +0,0 @@ -package io.optimism.batcher.loader; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; - -import io.optimism.batcher.TestConstants; -import io.optimism.batcher.telemetry.BatcherMetrics; -import io.optimism.type.BlockId; -import io.optimism.type.L1BlockRef; -import io.optimism.type.L2BlockRef; -import io.optimism.type.OpEthSyncStatusRes; -import io.optimism.type.RollupConfigResult; -import io.optimism.utilities.rpc.Web3jProvider; -import java.io.IOException; -import java.math.BigInteger; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; -import org.apache.commons.lang3.StringUtils; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.web3j.protocol.Web3j; -import org.web3j.protocol.core.methods.response.EthBlock; -import org.web3j.tuples.generated.Tuple2; - -/** - * test case of InnerWatcher. - * - * @author thinkAfCod - * @since 2023.05 - */ -class BlockLoaderTest { - - static LoaderConfig config; - static BigInteger blockNumber; - - @BeforeAll - static void setUp() throws IOException { - BlockLoaderTest.config = - new LoaderConfig(TestConstants.l2RpcUrl, TestConstants.rollupRpcUrl, mock(BatcherMetrics.class)); - } - - @AfterAll - static void tearDown() throws IOException {} - - @Test - void calculateL2BlockRangeToStore() { - var config = new LoaderConfig("http://fakeurl", "http://fakeurl", mock(BatcherMetrics.class)); - BlockLoader loader = spy(new BlockLoader(config, (unused) -> {})); - doReturn(new OpEthSyncStatusRes.OpEthSyncStatus( - null, - null, - new L1BlockRef("0xhead", BigInteger.valueOf(20L), null, null), // headl1 - null, - null, - new L2BlockRef("0xunsafel2", BigInteger.valueOf(21L), null, null, null, null), // unsafeL2 - new L2BlockRef("0xsafel2", BigInteger.valueOf(20L), null, null, null, null), // safeL2 - null, - null)) - .doReturn(new OpEthSyncStatusRes.OpEthSyncStatus( - null, - null, - new L1BlockRef("0xhead", BigInteger.valueOf(20L), null, null), // headl1 - null, - null, - new L2BlockRef("0xunsafel2", BigInteger.valueOf(20L), null, null, null, null), // unsafeL2 - new L2BlockRef("0xsafel2", BigInteger.valueOf(21L), null, null, null, null), // safeL2 - null, - null)) - .when(loader) - .requestSyncStatus(); - Tuple2 res = loader.calculateL2BlockRangeToStore(); - - assertNotNull(res.component1(), "start block id should not be null"); - assertNotNull(res.component2(), "end block id should not be null"); - assertTrue(res.component1().number().compareTo(res.component2().number()) <= 0); - - assertThrows(SyncStatusException.class, loader::calculateL2BlockRangeToStore); - } - - @Test - public void testLoadBlock() throws IOException { - if (StringUtils.isEmpty(TestConstants.l2RpcUrl) || StringUtils.isEmpty(TestConstants.rollupRpcUrl)) { - return; - } - - Web3j l2RpcClient = Web3jProvider.createClient(TestConstants.l2RpcUrl); - BlockLoaderTest.blockNumber = l2RpcClient.ethBlockNumber().send().getBlockNumber(); - l2RpcClient.shutdown(); - - var consumeCount = new AtomicInteger(); - var blockConsumer = (Consumer) block -> { - consumeCount.addAndGet(1); - }; - - BlockLoader loader = spy(new BlockLoader(config, blockConsumer)); - var mockedBlock = new EthBlock.Block(); - mockedBlock.setHash("testHash"); - mockedBlock.setNumber("0x123"); - doReturn(mockedBlock).when(loader).getBlock(any()); - doReturn(new Tuple2<>( - new BlockId("", BlockLoaderTest.blockNumber.subtract(BigInteger.valueOf(100L))), - new BlockId("", BlockLoaderTest.blockNumber.subtract(BigInteger.valueOf(80L))))) - .when(loader) - .calculateL2BlockRangeToStore(); - doReturn(null).when(loader).l2BlockToBlockRef(any(), any()); - doReturn(new RollupConfigResult()).when(loader).getRollConfig(); - loader.loadBlocksIntoState(); - assertEquals(20, consumeCount.get()); - assertEquals(loader.latestLoadedBlock.number(), mockedBlock.getNumber()); - } -} diff --git a/hildr-batcher/src/test/java/io/optimism/batcher/publisher/ChannelDataPublisherTest.java b/hildr-batcher/src/test/java/io/optimism/batcher/publisher/ChannelDataPublisherTest.java deleted file mode 100644 index 1f513390..00000000 --- a/hildr-batcher/src/test/java/io/optimism/batcher/publisher/ChannelDataPublisherTest.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.optimism.batcher.publisher; - -/** - * ChannelDataPublisher test case. - * - * @author thinkAfCod - * @since 0.1.1 - */ -class ChannelDataPublisherTest {} diff --git a/hildr-batcher/src/test/resources/ch_blocks.json b/hildr-batcher/src/test/resources/ch_blocks.json deleted file mode 100644 index b94df474..00000000 --- a/hildr-batcher/src/test/resources/ch_blocks.json +++ /dev/null @@ -1,1297 +0,0 @@ -[ - { - "number": "0xfed909", - "hash": "0xc7b2230e3da22619fe16011c508385da0b80a2ee9f86d4f5ff014a9c5945c512", - "transactions": [ - { - "blockHash": "0xc7b2230e3da22619fe16011c508385da0b80a2ee9f86d4f5ff014a9c5945c512", - "blockNumber": "0xfed909", - "hash": "0x9cc77a10a90fc10a0acdf04cb6b771f814102351717e5e4da5aa5496bab15afb", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181d0000000000000000000000000000000000000000000000000000000065421c30000000000000000000000000000000000000000000000000000000000000000aec8a872f5ca572df4c7e1989cc99627e0d086fb95f937b6c38ae303affff5cd100000000000000000000000000000000000000000000000000000000000000000000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0e0", - "r": "0x0", - "s": "0x0", - "sourceHash": "0x13722cdb0636e661c15021b7763e1a471c17a34c81150fa39768bf246677eaa6", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0xba25", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xe6e5700ce7550f1bd6e1f415db1561a03c1add9f52403933a28034ab4c3779d7", - "nonce": "0x0000000000000000", - "parentHash": "0x697fdae3863bd52085780a41cfc8d7b3abe23bf784308c19cc7c76473dad299f", - "receiptsRoot": "0x030b2afe4ffa211c38dc7bd40db30e3d64b2f8463e24ff7423a3bb84ba449a47", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x365", - "stateRoot": "0x2caaf3159a2c1d8a07e1c290cbeea0d993cb09077cf36a8c35b29f26fca1cd68", - "timestamp": "0x65421c76", - "totalDifficulty": "0x0", - "transactionsRoot": "0x408b142b4d1078fda5c294ac88b1b1386ec3b1ec3f557cfbcffa93d96976ee8c", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed90a", - "hash": "0x7057d89f6f6d1da401815eb2c736deb252dd1f9de404bc02f2373367af559e61", - "transactions": [ - { - "blockHash": "0x7057d89f6f6d1da401815eb2c736deb252dd1f9de404bc02f2373367af559e61", - "blockNumber": "0xfed90a", - "hash": "0xed96b592ff6d32d3aef85ba0c75313e78375225b019a11be61e37cb98bffe943", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181d0000000000000000000000000000000000000000000000000000000065421c30000000000000000000000000000000000000000000000000000000000000000aec8a872f5ca572df4c7e1989cc99627e0d086fb95f937b6c38ae303affff5cd100000000000000000000000000000000000000000000000000000000000000010000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0e1", - "r": "0x0", - "s": "0x0", - "sourceHash": "0xef1e4a151be7900e9c610d16d1524b24357c3919b80c93c5aa8d398ca939420d", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - }, - { - "blockHash": "0x7057d89f6f6d1da401815eb2c736deb252dd1f9de404bc02f2373367af559e61", - "blockNumber": "0xfed90a", - "hash": "0xfabb9749531c86379b531421980865eb895cdd9a3bf58f70135b335599a906f4", - "accessList": [], - "chainId": "0x1a4", - "from": "0x9cc971e84fe5d09d0967f15ae05dfd553c5a1fa6", - "gas": "0xe425e", - "gasPrice": "0x5f5e132", - "input": "0xb630d432000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e0594196130fab5e6eb6cb6c936e20185243dc9756e285ee0ce269d8a5877ac917b35cabe1740f4f381598bd2680c0e10cab6fe26f32c53c8f2ee0f02c023eeb8900000000000000000000000000000000000000000000000000000000000ff2cd000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6f7074696d69736d2d676f65726c69000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020e18f442de5d60407d0f5ff214a3ef3fb3289d28f7a395f7cf511041ccac953570000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000200fb000000000000000000000000e543df75c1283a2b023f42f49640c37f10c7c1cb0000000000000000000000004ae7298d7edad7f1b0dabda4407fbabf78e2d59b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000046f6d6e6900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6f7074696d69736d2d676f65726c69000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a492056d8500000000000000000000000094e2cffd3a5ae36180905aaa81b538a816e63949000000000000000000000000000000000000000000000001d7d843dc3b480000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000046f6d6e69000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041fafcf2627b2eedcc896b5eef7455097aa448e6532d049b1531c97781db7f1465358502d5990f93e977a7499c5a11ce1c0a92e8c8b8143770e71a77909b1ab95d1c00000000000000000000000000000000000000000000000000000000000000", - "maxFeePerGas": "0x5f5e164", - "maxPriorityFeePerGas": "0x5f5e100", - "nonce": "0x9ef87", - "r": "0x5ddabc95dbdf204a5f472ff5202284f58ada1363d6426a6fbb8814ec150a198b", - "s": "0x35bd1a598af8535b597e49dd5018a8f7ed182f258e5abe88c4f8b458d9826caf", - "to": "0xcbbc5da52ea2728279560dca8f4ec08d5f829985", - "transactionIndex": "0x1", - "type": "0x2", - "v": "0x0", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0xe6a2d", - "logsBloom": "0x0008000000000000000010200000000204000000000000000000400000000000000000000000000000080000000000000000000000000000010000008000000004000000000000000000000a101000000000000000000208000400000000000000080000020000000000000000000800000000000800000000000010000001000000000000000840000000000000000000000000000000000000000004000000000010000000000000000000800000040000020001000000000000000000000000000002000000000000000000000000000000000000001000000002400020000000000000000000000000002804000000080000080000000000000000000020", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xe6e5700ce7550f1bd6e1f415db1561a03c1add9f52403933a28034ab4c3779d7", - "nonce": "0x0000000000000000", - "parentHash": "0xc7b2230e3da22619fe16011c508385da0b80a2ee9f86d4f5ff014a9c5945c512", - "receiptsRoot": "0x8e44f3e9a11974769d66a9b001b96e861c1728af260fb828ce5feac44008f9ae", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x963", - "stateRoot": "0x7b1dcc908b67e58122c4eb89f0a25c1efd2767a24dc0416b8c3214d67d8fba18", - "timestamp": "0x65421c78", - "totalDifficulty": "0x0", - "transactionsRoot": "0x63aa6510d5abaf2d6dbe82655f5af0067e5d69a6f8950dc9c9d3af3c2bd99e97", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed90b", - "hash": "0xa45929fae4af65d69b4a942b67e33a8cfd079603a1e5b8a7fcea1bc116f90879", - "transactions": [ - { - "blockHash": "0xa45929fae4af65d69b4a942b67e33a8cfd079603a1e5b8a7fcea1bc116f90879", - "blockNumber": "0xfed90b", - "hash": "0xde8b0fdf8573e94433c0d8192f386e39e84abdc510f87470935cb9853a1a2a24", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181d0000000000000000000000000000000000000000000000000000000065421c30000000000000000000000000000000000000000000000000000000000000000aec8a872f5ca572df4c7e1989cc99627e0d086fb95f937b6c38ae303affff5cd100000000000000000000000000000000000000000000000000000000000000020000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0e2", - "r": "0x0", - "s": "0x0", - "sourceHash": "0x1bf4d0d4f1f7cd61fd3fa0a1449145b2d475b56cb6230079622251c5b36670a5", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - }, - { - "blockHash": "0xa45929fae4af65d69b4a942b67e33a8cfd079603a1e5b8a7fcea1bc116f90879", - "blockNumber": "0xfed90b", - "hash": "0xcf9c0827e21faf373ba10c5cf24a4a56eb6953fc9d65d72885cab51e3f6175d6", - "accessList": [], - "chainId": "0x1a4", - "from": "0xb0c0f73f84ce7355e755846c123f0a5848304b52", - "gas": "0xf4240", - "gasPrice": "0x9502f932", - "input": "0x1249c58b", - "maxFeePerGas": "0x9502f964", - "maxPriorityFeePerGas": "0x9502f900", - "nonce": "0x2", - "r": "0x949ec41c0879211f8887d5164041d6188edc2c794a5a1d246ecf0d0eb6d35ffb", - "s": "0x57e80d08a5ae1f41c52017d8c03e9f1b434ba8040e2f88ae63a2110081324d5", - "to": "0x222e406c60dcda91e688afadbad5742c858e57a0", - "transactionIndex": "0x1", - "type": "0x2", - "v": "0x0", - "value": "0x0" - }, - { - "blockHash": "0xa45929fae4af65d69b4a942b67e33a8cfd079603a1e5b8a7fcea1bc116f90879", - "blockNumber": "0xfed90b", - "hash": "0xa691797770acbb5f94c529118e95527a9d5c71ab0b06165051889b195294d1c0", - "accessList": [], - "chainId": "0x1a4", - "from": "0x784e83fc9aa0ebbbeb56985d557d5b433ada1713", - "gas": "0x5b8d80", - "gasPrice": "0x5f5e132", - "input": "0xb1dc65a4000168fe4aeb6129d7251e28b38e5f27d5b3cea6548afead1311cfdb9447870b00000000000000000000000000000000000000000000000000000000007a15031e10c4d40e18ac947a55da7035300b2585acf048a43764c44082c5f0d1c282db00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000030001000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000005ca20000000000000000000000000000000000000000000000000000000000005ca20691e3b307ece8ad343c0c2c5a1dcc2aa1ec2b9a119ebb5abc75dbcdd0a8868700000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006434c12200af19a933c2b39525e1e33639b98bc01adebeb02c9be073c28c53b1d881bd1c5940e5a978bff3b61df355779c55677a89d266394805684d412554361c8cfdead0404ad831be7e93a1c0baba1ad5ea60ba15b9a8b35d49d4d12caf895fd48549df3ace9dc4febd7782fdd84c99e9f0e2940699ee296fba17bd1fe52a36c07502dde9839d2cd661f7c8ea9a3d47419910e26541cc73bb21ddd81a65f3030de928d1ebb7d1005b224c41961bf89a095b823baf1e9c330924a221268597d00000000000000000000000000000000000000000000000000000000000000066a5206c67c00adb657b333410aadb1e7915f0bb28f5add721cf33090d71897e33544e99677de19b5c18c1bd71ba7672bb2f02f7512fc62fbf5237e23382b5c3155913c53063b161b5c0ef4499ed8463bdb6f273f30d5f056f22c94cf82c467fd04a41f901d5dc4f1ba7365d9ffbf021b4ca0f9259e30a71945e63bf2e58811df4c0c60881eb5d1a2e4aecd17acf6315d0464ba85020997d0aa92f0a6e2429e5b38203c79db88875af3d32d2e9bcc0a33f74d088a23e3ab1a2db328c3977c94b5", - "maxFeePerGas": "0x5f5e132", - "maxPriorityFeePerGas": "0x5f5e100", - "nonce": "0x2f8a", - "r": "0x23a2b3ab7c3b230ce629c9e8858081aa7d0436ed2a03ae9c75a2b8a65433f85e", - "s": "0x15c6e06e724b141e4438459718615d10f81fc1271f10b8e836ede0ecf15ec9aa", - "to": "0x4f57b2d4b3b42f09cd7ef48254d2c31b6b525763", - "transactionIndex": "0x2", - "type": "0x2", - "v": "0x1", - "value": "0x0" - }, - { - "blockHash": "0xa45929fae4af65d69b4a942b67e33a8cfd079603a1e5b8a7fcea1bc116f90879", - "blockNumber": "0xfed90b", - "hash": "0xbbd4f254ca0cbada309e275cd1911233e4f54154b3c939355fef8caf60f8362a", - "accessList": [], - "chainId": "0x1a4", - "from": "0x3b497482adc590834cae8a0c7eaa7a67994e522c", - "gas": "0x5b8d80", - "gasPrice": "0x5f5e132", - "input": "0xb1dc65a40001e50f36f6449d45e7765580d00582234b527630572a1380ac70383a66a46400000000000000000000000000000000000000000000000000000000006c14038ef7f88cf6cfe3d6d52cffa8584f12f9333bbb48801769a9bfc55ca502cd49d700000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000003000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000156600000000000000000000000000000000000000000000000000000000000015662f4bf7005c5a0435535ca3e2d5d1e2be046607f68d00dc47d6fea7b703d30832000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064bd1776c5cf283c2ca56eb2d63483c291dad641a4602fe785febe1b00c771f69abe6da82554797432b84e63a2b203ce66a45c9ac87776d9fdddf45a4847c591dd18a7fcec8add0ce57a994baf6aeb65e9fccdbd91177d6b75fc14805f2cd6b00f77a2c857bfd67785c3f89567d9501b142bc5b35970c4263ab4b2ee46b87c0c3f25819101a0e05bd0e8e3afbee19a418410396560fa939f983237e364214955345892d6c9187a6841789785c2d86011e496d31fef7191cbe5eae0818baff8713000000000000000000000000000000000000000000000000000000000000000668668939461cf52dfa6bc6331dcc9bd42797201bf9f9e89ce2d4398b80fd787b5805bcea94dc09d1dc99949a2bb6cde0b1a6758d3ac94626ceed4168777cc55e4e5ec877a52d89e9bee2f1d1822cfdb1f1d5cd46b54e4934e17edeb9f01c87376b3c472bffed2919853e34aada54fa31fb018f6a6e7a4c64c6019a2db14dff16368af9a43ce94c432c5a1bf587524234513b6f09e6e026ef31e16e48bf7ad7bf6bf1e47d52cd46207ddac30708ccecc33ccb1ffdad089216ea163b1d09492c39", - "maxFeePerGas": "0x5f5e132", - "maxPriorityFeePerGas": "0x5f5e100", - "nonce": "0xa280", - "r": "0x9f14c375a2efcff35fcdd9543113bf358b0bffca2ea6ab7794856bbcbdfd8e9a", - "s": "0x7f20b7ac61daf217337744999f5ce447056c7e70a9e6378a13fe2fa2b4a8c646", - "to": "0x2980de4ce178bc8bb6840abd2ef0e2a7c8e7272f", - "transactionIndex": "0x3", - "type": "0x2", - "v": "0x1", - "value": "0x0" - }, - { - "blockHash": "0xa45929fae4af65d69b4a942b67e33a8cfd079603a1e5b8a7fcea1bc116f90879", - "blockNumber": "0xfed90b", - "hash": "0xf19719ce101491bba7deb7f5bdcc772355e2b156c9e9da6e56fc65d4134e6689", - "accessList": [], - "chainId": "0x1a4", - "from": "0x365252db0066fb7101994a8d04e4e25ca9ff2a5f", - "gas": "0xe4e1c0", - "gasPrice": "0x64", - "input": "0xd985f1e8000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000b47f1e0035f15998fdd0999646eac1bc5aa8bd90000000000000000000000002cfdb5d233d8029ccb07aad2ca7a558bfccf48120000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002447189fd3fca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a6000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001cb504e41550100000000a00100000000010004172835280596ef1f0ad40b8b09992e82ac5d96b8cc6770dfff1f79db6a2f6433fcad1cc0e45f76572e6b38aff1e1d6e66446f9e0a6d1040590fb2012ead5cf0165421c7300000000001ae101faedac5851e32b9b23b5f9411a8c2bac4aae3ed4dd7b811dd1a72ea4aa71000000000203006d01415557560000000000066a86ad00002710d39a6088fed6117d6d7927cd8767a31af05e05c801005500ca80ba6dc32e08d06f1aa886011eed1d77c77be9eb761cc10d72b7d0a2fd57a60000002a0fb422fc0000000002cb5af6fffffff80000000065421c730000000065421c710000002a09a48b880000000002bb683b0a0e509230bc887125c2e11101e392a111ba60982690fe64c2b70d1a28d86d96ff9748d0bd2cbac47f756f18562cc6506da404aca909d70ff20d09647f2214569c08524a88d2e7e376e761e736c4fd9a13e92bd9b5b48561a93384067f9eb1aad3f53617572311d145c5dfca5bc537eb4942142676c081adeb501a0a36c59c90ce6eed693b822afd66a129f6ead59c1db9fb16ed5e23deff812436de0f5e59a2024a9fc7b84db1145603710d0fda72a67944534c44716512e1c91af4a19e1c7e0346d677d291162b6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000648c34d6be00000000000000000000000000000000000000000000000000000000000000dd0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "maxFeePerGas": "0x5f5e100", - "maxPriorityFeePerGas": "0x32", - "nonce": "0x3f0c", - "r": "0xb3bb26e245851a23a4d985aa9a03b615ddf62d47568e59e151b1ebb7d6ae7cd3", - "s": "0x3dbb22da256d7b6e8789fda4bff1d6791b5867699c1bfadc3da38e8edf1efe7c", - "to": "0x00000000002fd5aeb385d324b580fca7c83823a0", - "transactionIndex": "0x4", - "type": "0x2", - "v": "0x1", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0x140c73", - "logsBloom": "0x000000000000000006000020001002000001000010000000000000000000000000000000000200000003000000200000000200000000008000000000000600000000010008000000000000080000000080000000000420005006010000020020c18000000300000000400000400009000004000000010000000000100100000001000100000003020100000080000010000000000000000000000000000000000100000000000000200000000000001000000000000000011000000000000000000005021000000000008084c0022000000000000000010400001100008064000081000004000080000000000000100000010000000000000000008280800000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xe6e5700ce7550f1bd6e1f415db1561a03c1add9f52403933a28034ab4c3779d7", - "nonce": "0x0000000000000000", - "parentHash": "0x7057d89f6f6d1da401815eb2c736deb252dd1f9de404bc02f2373367af559e61", - "receiptsRoot": "0x9a9dd846e8b11fcd0d43e5e0c353f91c14294cdeafd7ed48d5a21e575f6ce230", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x11ac", - "stateRoot": "0xec94c0c78d07a9a81b5d2e8fb8ce653812b0c3f7d5252a1bc2ec3925dc592093", - "timestamp": "0x65421c7a", - "totalDifficulty": "0x0", - "transactionsRoot": "0xfc42c02840271baaf3342ebf55491dd1338a53d781207d887fdbe566349d3651", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed90c", - "hash": "0xc3b4c03658a2d44fcb66a254395fefe31326a2cf90c56183425f90b51724908a", - "transactions": [ - { - "blockHash": "0xc3b4c03658a2d44fcb66a254395fefe31326a2cf90c56183425f90b51724908a", - "blockNumber": "0xfed90c", - "hash": "0x8c3cacd6aff46ba107216a6b03e92b84a197f074af2813373d63a63f20a39793", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181d0000000000000000000000000000000000000000000000000000000065421c30000000000000000000000000000000000000000000000000000000000000000aec8a872f5ca572df4c7e1989cc99627e0d086fb95f937b6c38ae303affff5cd100000000000000000000000000000000000000000000000000000000000000030000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0e3", - "r": "0x0", - "s": "0x0", - "sourceHash": "0xc425acac055a6da6b168e1ef788495ab26b7c6dac1d5950e41c0347135c59eab", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - }, - { - "blockHash": "0xc3b4c03658a2d44fcb66a254395fefe31326a2cf90c56183425f90b51724908a", - "blockNumber": "0xfed90c", - "hash": "0x1a653d109a277ec42814fb520e84349c2ab089df02ce64c6e6fca511e911c59f", - "accessList": [], - "chainId": "0x1a4", - "from": "0xbbe9daf8010fecbea38a39f64dac16ea6b1cdcbe", - "gas": "0x2e89b", - "gasPrice": "0x59682f32", - "input": "0x110410f700000000000000000000000000000000000000000000000000000000013bd8cf", - "maxFeePerGas": "0x59682f3c", - "maxPriorityFeePerGas": "0x59682f00", - "nonce": "0x2a", - "r": "0xf6a25b71ecd861d59228fb5b088c0618406d05d145a4eac27c42382b9bb04248", - "s": "0x30d5d5725351ac39fd1c77efa2cd7cc19e868a1ffd151fb49ee3e05c674cced3", - "to": "0xd6047245e0fc9baa6231cd8d013b1118b5042aa9", - "transactionIndex": "0x1", - "type": "0x2", - "v": "0x1", - "value": "0xb5e620f48000" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0x39fac", - "logsBloom": "0x00000000000000000000000000008000000000000000000000000000000000000000000001000000000000000000000000000080000000000000000000000000000000001000000001000008002000000000000000000000000000000000000000000000020040001000040000000800000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000010002000001000000000000000000000000000000000000800000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000000020000000000000000000000000000000000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xe6e5700ce7550f1bd6e1f415db1561a03c1add9f52403933a28034ab4c3779d7", - "nonce": "0x0000000000000000", - "parentHash": "0xa45929fae4af65d69b4a942b67e33a8cfd079603a1e5b8a7fcea1bc116f90879", - "receiptsRoot": "0x6a8fb2ab22ec1231706342803f5a0f2661295dd98ee9d503de02d2ee9279db37", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x402", - "stateRoot": "0xf9cb7230cd8f6c78878e60a13edd42a2b247547a6528d793566c1e9f63948040", - "timestamp": "0x65421c7c", - "totalDifficulty": "0x0", - "transactionsRoot": "0x47119266cd1a22f0dbe3b536da55c5752eb687703fa08d781f10f731e219ea19", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed90d", - "hash": "0x14fbcf40d43e38c135d03c6b6df429c1f7ab190f334ec7e52eb1b4634a1de757", - "transactions": [ - { - "blockHash": "0x14fbcf40d43e38c135d03c6b6df429c1f7ab190f334ec7e52eb1b4634a1de757", - "blockNumber": "0xfed90d", - "hash": "0xcaf761c36e4b92c8fd928457f6bdb271c86c6ac8c249609682b13bf8a0e9bf12", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181d0000000000000000000000000000000000000000000000000000000065421c30000000000000000000000000000000000000000000000000000000000000000aec8a872f5ca572df4c7e1989cc99627e0d086fb95f937b6c38ae303affff5cd100000000000000000000000000000000000000000000000000000000000000040000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0e4", - "r": "0x0", - "s": "0x0", - "sourceHash": "0xd70b9335dd6c98a3a268466673ad34b3f934c1f984b0c5e1e4c918ef6bfd0c30", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - }, - { - "blockHash": "0x14fbcf40d43e38c135d03c6b6df429c1f7ab190f334ec7e52eb1b4634a1de757", - "blockNumber": "0xfed90d", - "hash": "0xee06bfaa5a219ab12a94b3bf1ea09753264b5dbe8198881408d1e40b30f9b1f3", - "accessList": [], - "chainId": "0x1a4", - "from": "0x3540e1f097a7d6bfce706224dcc965a26c5baa7c", - "gas": "0x11170", - "gasPrice": "0x5d21dba32", - "input": "0x97998611000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000004f57b2d4b3b42f09cd7ef48254d2c31b6b5257630691e3b307ece8ad343c0c2c5a1dcc2aa1ec2b9a119ebb5abc75dbcdd0a88687", - "maxFeePerGas": "0xba43b7400", - "maxPriorityFeePerGas": "0x5d21dba00", - "nonce": "0x102b", - "r": "0xe45cafb3673736026cac65017fcfc7ce56cd95bcd6f78bbe1bbd6260ef00683b", - "s": "0x5a7e696f25429bbeb035a60f8dcb7d3af2420f0fa339c38b2b01d4e916116fb5", - "to": "0xeaf6968fab9c54ac31c3679f120705b5019d3546", - "transactionIndex": "0x1", - "type": "0x2", - "v": "0x0", - "value": "0x0" - }, - { - "blockHash": "0x14fbcf40d43e38c135d03c6b6df429c1f7ab190f334ec7e52eb1b4634a1de757", - "blockNumber": "0xfed90d", - "hash": "0x8e74f3b7bb111162929b7318ccb143ca669fa2273ebdd8a09e9fd578edda5a85", - "accessList": [], - "chainId": "0x1a4", - "from": "0x4d9987720ec678aa1271621ffe617771288e436f", - "gas": "0x11170", - "gasPrice": "0x5d21dba32", - "input": "0x97998611000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000004f57b2d4b3b42f09cd7ef48254d2c31b6b5257630691e3b307ece8ad343c0c2c5a1dcc2aa1ec2b9a119ebb5abc75dbcdd0a88687", - "maxFeePerGas": "0xba43b7400", - "maxPriorityFeePerGas": "0x5d21dba00", - "nonce": "0x19b1", - "r": "0x616bce30ef5741f3dd525b97547f14c035aa0637b065fc36c94f1a475076f3c7", - "s": "0xaafe09ae83e4ccd42a3c44e203369fa46f2921b230ff9c7ed525a4abfd515eb", - "to": "0xeaf6968fab9c54ac31c3679f120705b5019d3546", - "transactionIndex": "0x2", - "type": "0x2", - "v": "0x1", - "value": "0x0" - }, - { - "blockHash": "0x14fbcf40d43e38c135d03c6b6df429c1f7ab190f334ec7e52eb1b4634a1de757", - "blockNumber": "0xfed90d", - "hash": "0xf4a4b5d7cc789fd61b37d20ea75e26d615ebb155a5ad25866f4ab3ccb222f4f6", - "accessList": [], - "chainId": "0x1a4", - "from": "0x9cc971e84fe5d09d0967f15ae05dfd553c5a1fa6", - "gas": "0x405ac", - "gasPrice": "0x5f5e132", - "input": "0xb630d432000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e0b35cabe1740f4f381598bd2680c0e10cab6fe26f32c53c8f2ee0f02c023eeb890911e63c580e836787004eb8dd2f9ed91a1f1e5a0e967d86e895a2b3ddf339cc00000000000000000000000000000000000000000000000000000000000ff2ce000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6f7074696d69736d2d676f65726c690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041dfcb74b61aca7b7ef90e9e5221ffa2d54f12551b1750cb5fc87e3e3b9dab7ffb7daa0f2dce7e9058e183c558af051bada0e802ff5c311199cb27159686c90fdc1b00000000000000000000000000000000000000000000000000000000000000", - "maxFeePerGas": "0x5f5e164", - "maxPriorityFeePerGas": "0x5f5e100", - "nonce": "0x9ef88", - "r": "0xe88d3e7ad186ebbf03bbedba92ab96fba2ebbf25b8e22141673ada6ea42c3e87", - "s": "0xb60ef654e913b8b5b02fadcfad516a61c58159368b24b234135860366c5c546", - "to": "0xcbbc5da52ea2728279560dca8f4ec08d5f829985", - "transactionIndex": "0x3", - "type": "0x2", - "v": "0x1", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0x56cbb", - "logsBloom": "0x00000000000000000000100000000000000000000000000000000000000000020000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000000000000010000000000000000080001000000000000000000000000000000000000000000000000000001004000000000000004000000000000000000120000000000008000000004000000000010000000000000000000000004004000000000800000000000000000400000000101000000004000000000000000000000004000000000000002000000000000000000020001000000000000000000000000000000000000000100000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xe6e5700ce7550f1bd6e1f415db1561a03c1add9f52403933a28034ab4c3779d7", - "nonce": "0x0000000000000000", - "parentHash": "0xc3b4c03658a2d44fcb66a254395fefe31326a2cf90c56183425f90b51724908a", - "receiptsRoot": "0xc6deb0e17d071eab845c4c3556721aa96a920ae7b9670166f9fc2574b1a95e9f", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x899", - "stateRoot": "0xebaf3a68b7cbc81eeb7a48de6f03c4f30b798bf37efdf43e52fd6d78b45463e9", - "timestamp": "0x65421c7e", - "totalDifficulty": "0x0", - "transactionsRoot": "0xd07f6cad26c1cba71c40f0ffb8592549e550c4e4bf7a4823eab2c2128fd84d31", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed90e", - "hash": "0x3d1212b2a39a8b9066dd168a0a90f2e596a7652fb3df2ed2559df741f5caaa8b", - "transactions": [ - { - "blockHash": "0x3d1212b2a39a8b9066dd168a0a90f2e596a7652fb3df2ed2559df741f5caaa8b", - "blockNumber": "0xfed90e", - "hash": "0x18ffab593442e214ddf7eb10acf41ff84f34f483e8738b88b6c6c5ac3b9a7eef", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181d0000000000000000000000000000000000000000000000000000000065421c30000000000000000000000000000000000000000000000000000000000000000aec8a872f5ca572df4c7e1989cc99627e0d086fb95f937b6c38ae303affff5cd100000000000000000000000000000000000000000000000000000000000000050000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0e5", - "r": "0x0", - "s": "0x0", - "sourceHash": "0x84fadd5918311710d87353233066b621bcb369dbc0a82b82021469de3a1a2252", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0xb711", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xe6e5700ce7550f1bd6e1f415db1561a03c1add9f52403933a28034ab4c3779d7", - "nonce": "0x0000000000000000", - "parentHash": "0x14fbcf40d43e38c135d03c6b6df429c1f7ab190f334ec7e52eb1b4634a1de757", - "receiptsRoot": "0x29079b696c12a19999f3bb303fddb6fc12fb701f427678cca24954b91080ada3", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x365", - "stateRoot": "0x837f2da981198bd4ac3a300180917214238b28b3a48a6a2ef9c59d6b6f216509", - "timestamp": "0x65421c80", - "totalDifficulty": "0x0", - "transactionsRoot": "0xfe24abf581a58419f6a3f9af17ebe12cb38f06b30668751b8e1ed52957b73523", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed90f", - "hash": "0x9ec60db2a10a95df14532962ddd614ede91d1e7e0050dd35cd1b80c32c35bd74", - "transactions": [ - { - "blockHash": "0x9ec60db2a10a95df14532962ddd614ede91d1e7e0050dd35cd1b80c32c35bd74", - "blockNumber": "0xfed90f", - "hash": "0xa70de9ed96bdb201a7bb26072e078a5516b96741f9ea7b1314cc3585876d05c4", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181d0000000000000000000000000000000000000000000000000000000065421c30000000000000000000000000000000000000000000000000000000000000000aec8a872f5ca572df4c7e1989cc99627e0d086fb95f937b6c38ae303affff5cd100000000000000000000000000000000000000000000000000000000000000060000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0e6", - "r": "0x0", - "s": "0x0", - "sourceHash": "0xfa3a0d15d3bc4a30ddfedcb6f7df081e88e9eb700a289a16d9d89c9f83ba263c", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - }, - { - "blockHash": "0x9ec60db2a10a95df14532962ddd614ede91d1e7e0050dd35cd1b80c32c35bd74", - "blockNumber": "0xfed90f", - "hash": "0x42a20020d307d1fd18e9b4834daaba50b421ad0a675293557dccc3eb8e6da0d9", - "accessList": [], - "chainId": "0x1a4", - "from": "0x0b2dfb982114d57033c66a25a5d46957e93cb22f", - "gas": "0x7a120", - "gasPrice": "0x7270e3c", - "input": "0xc9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000020001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000038cfbf2a1a6b566666843f13294431710009423306030002010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000053c219328000000000000000000000000000000000000000000000000000000053c5cca66000000000000000000000000000000000000000000000000000000053c5cca66000000000000000000000000000000000000000000000000000000053c64f5f000000000000000000000000000000000000000000000000000000000000000024a61aa0cb5f60bd5ff7ae8f5d6f8c81cb741022255e8b70d0bf8c86209f01e118a2454b0f732f2737caf08790f6630475094e0893e965171b2ae5614a113ae6800000000000000000000000000000000000000000000000000000000000000024d3a08476f0041778f0589a3f1be7a22d82264663e659c8e1167a046bffe7db4292770a1e807b7fe993adb6b560b2aad3309f46d4db76e40c2dcd9c3caeecf38", - "maxFeePerGas": "0x7270e5a", - "maxPriorityFeePerGas": "0x7270e0a", - "nonce": "0x78ad9", - "r": "0x2fbf875de340747f7a71e9f07d29cd1029a85956413085a040cc5f0318c0e6dd", - "s": "0x7b179d1601d543c053cf3fec0f576213e0293ba2050b9681729bd61e1bbc8274", - "to": "0x40a8b760a86aa0ea51bb6c2831082ab70145b9fc", - "transactionIndex": "0x1", - "type": "0x2", - "v": "0x1", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0x2afdb", - "logsBloom": "0x00000000000000000000000800000000000000000000000000000000000000000000100000000000000000000000000000000000000200000000000000000000000000000000000000001021002000000000000001000000000000000000001000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000040000480000000010000000000400000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000020000000000000000000000000000000080000010000000000000000000000000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xe6e5700ce7550f1bd6e1f415db1561a03c1add9f52403933a28034ab4c3779d7", - "nonce": "0x0000000000000000", - "parentHash": "0x3d1212b2a39a8b9066dd168a0a90f2e596a7652fb3df2ed2559df741f5caaa8b", - "receiptsRoot": "0xda248b89fd5a8d0f7a17ac45acd9d9c5ea52a1e617074a8831e08f3e9eb70d70", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x643", - "stateRoot": "0x917571f029fbe4bbe03199e1a05a609d2e3eef7bdc9c6248f9a6757b8d659b34", - "timestamp": "0x65421c82", - "totalDifficulty": "0x0", - "transactionsRoot": "0x1418b59412f84bad5365026990791aac796eb4f51fb7b258cda61a4223a9298b", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed910", - "hash": "0xd9616b463fc5c504c11591a240a33fa7ab0333fa583d8e61a3cfe74a7275c81e", - "transactions": [ - { - "blockHash": "0xd9616b463fc5c504c11591a240a33fa7ab0333fa583d8e61a3cfe74a7275c81e", - "blockNumber": "0xfed910", - "hash": "0x5144d13c65a18ada65d2b3e5bab4bb3a6075efc1ef9dfdcef9bbc8624c987c78", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181d0000000000000000000000000000000000000000000000000000000065421c30000000000000000000000000000000000000000000000000000000000000000aec8a872f5ca572df4c7e1989cc99627e0d086fb95f937b6c38ae303affff5cd100000000000000000000000000000000000000000000000000000000000000070000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0e7", - "r": "0x0", - "s": "0x0", - "sourceHash": "0x28fddacc9458f7f7a38f9c640e176934b691a3894d5ef5b0a5e358f4c57c5abb", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - }, - { - "blockHash": "0xd9616b463fc5c504c11591a240a33fa7ab0333fa583d8e61a3cfe74a7275c81e", - "blockNumber": "0xfed910", - "hash": "0xd77b6c3c5d31ccd7926aedc1c8a14f6b959f742399fe8bfd2382cd6440e25b30", - "accessList": [], - "chainId": "0x1a4", - "from": "0x9cc971e84fe5d09d0967f15ae05dfd553c5a1fa6", - "gas": "0x50c5d", - "gasPrice": "0x5f5e132", - "input": "0xb630d4320000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000e00911e63c580e836787004eb8dd2f9ed91a1f1e5a0e967d86e895a2b3ddf339cc25b0456d3aa978072457cd416b58c8824bdd9ee8ed8852dfbb799b962325b69200000000000000000000000000000000000000000000000000000000000ff2cf000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6f7074696d69736d2d676f65726c690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e025b0456d3aa978072457cd416b58c8824bdd9ee8ed8852dfbb799b962325b6925818ed0aa3671b7ea18623aa1e7e4093186e08063ddb2b873c0878d6bacdaa9500000000000000000000000000000000000000000000000000000000000ff2d0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6f7074696d69736d2d676f65726c6900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041a0b45fdada067eef2162f37208a5bc1a80c4673a59e701687d4b9a8ce8fb184f7c880ed0a9293be30c01b7351aebb222fa44ac5bead5e3f07370c9c31dcbcb171b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041fd9d15522aa97beccf2e247e65b566f7d1f9c48ee4a66b763209e12d287d33616d7923732d616450358d423798fa04358700cf4b27175683e120a11653da03dd1c00000000000000000000000000000000000000000000000000000000000000", - "maxFeePerGas": "0x5f5e164", - "maxPriorityFeePerGas": "0x5f5e100", - "nonce": "0x9ef89", - "r": "0x3114f4c94a70d9ca807b52fcfb1468b14fa939fd698e68f1600296ed0559ab47", - "s": "0x2e7c8bcb0f07dedad5d7894e95ef95bf3dabd648dcdc8e2c583a4e9d80e678fe", - "to": "0xcbbc5da52ea2728279560dca8f4ec08d5f829985", - "transactionIndex": "0x1", - "type": "0x2", - "v": "0x1", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0x5b1aa", - "logsBloom": "0x00000000100000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000081000000000000000000000010000000000000000000000000000000000004000000000010000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000020002000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xe6e5700ce7550f1bd6e1f415db1561a03c1add9f52403933a28034ab4c3779d7", - "nonce": "0x0000000000000000", - "parentHash": "0x9ec60db2a10a95df14532962ddd614ede91d1e7e0050dd35cd1b80c32c35bd74", - "receiptsRoot": "0xa159a1cc9a597b22e46260e498c984948363ba0cbe1d2f99033543f1382dfdff", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x8e3", - "stateRoot": "0xf96c68b3db6ef664a94f1e79cceabfa27a8ed788965cf7e2bb346cd90fc74f73", - "timestamp": "0x65421c84", - "totalDifficulty": "0x0", - "transactionsRoot": "0x3b19486c1a59a65cdd817b060b1d1bc2edc8b3102f36c747bbf466eedbd67ab4", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed911", - "hash": "0x99b274f47e55c04dee02571d87a82e514f66228019d6c1b9986da0330fdc21bf", - "transactions": [ - { - "blockHash": "0x99b274f47e55c04dee02571d87a82e514f66228019d6c1b9986da0330fdc21bf", - "blockNumber": "0xfed911", - "hash": "0xa633bcaae71bec4e74d6654faf7d832fa17342dc3eee9137868df95dd5a40b2d", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181d0000000000000000000000000000000000000000000000000000000065421c30000000000000000000000000000000000000000000000000000000000000000aec8a872f5ca572df4c7e1989cc99627e0d086fb95f937b6c38ae303affff5cd100000000000000000000000000000000000000000000000000000000000000080000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0e8", - "r": "0x0", - "s": "0x0", - "sourceHash": "0x641a1442a989615a9b07958bdaaf226d64389d8527b4e0f64df90446b52c37b0", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0xb711", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xe6e5700ce7550f1bd6e1f415db1561a03c1add9f52403933a28034ab4c3779d7", - "nonce": "0x0000000000000000", - "parentHash": "0xd9616b463fc5c504c11591a240a33fa7ab0333fa583d8e61a3cfe74a7275c81e", - "receiptsRoot": "0x29079b696c12a19999f3bb303fddb6fc12fb701f427678cca24954b91080ada3", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x365", - "stateRoot": "0x8e50fe5b6cbdc91c5acbb658c2919969bc557190079a0ad3d7eaaac0bce2dae1", - "timestamp": "0x65421c86", - "totalDifficulty": "0x0", - "transactionsRoot": "0x73f3b92b28dd4a74dfda16b7231e213236a4a5aae2ee1f8a9cef22c5d0b1edf6", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed912", - "hash": "0x7c6bc4bdd2b2b627f1abce0b056a8b2865be7a78135c402247991c74352cb523", - "transactions": [ - { - "blockHash": "0x7c6bc4bdd2b2b627f1abce0b056a8b2865be7a78135c402247991c74352cb523", - "blockNumber": "0xfed912", - "hash": "0xb09e05155f69426a2a83f6058bc0f8bcdec13a3b17f4941f1995993958bae0d8", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181d0000000000000000000000000000000000000000000000000000000065421c30000000000000000000000000000000000000000000000000000000000000000aec8a872f5ca572df4c7e1989cc99627e0d086fb95f937b6c38ae303affff5cd100000000000000000000000000000000000000000000000000000000000000090000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0e9", - "r": "0x0", - "s": "0x0", - "sourceHash": "0x40359ca320e94c644c2d3c70931e00bb8392c185bcbcf8aa4dc5ada7d8a23b1b", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - }, - { - "blockHash": "0x7c6bc4bdd2b2b627f1abce0b056a8b2865be7a78135c402247991c74352cb523", - "blockNumber": "0xfed912", - "hash": "0xdc70fb04e1c7122055e6d929d56710a7ea5fea4518b348ebff1b6e4787bf6b2a", - "accessList": [], - "chainId": "0x1a4", - "from": "0xbbe9daf8010fecbea38a39f64dac16ea6b1cdcbe", - "gas": "0x493e0", - "gasPrice": "0x59682f32", - "input": "0x2d3e085100000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000002", - "maxFeePerGas": "0x59682f3c", - "maxPriorityFeePerGas": "0x59682f00", - "nonce": "0x2b", - "r": "0xe8c2d8a6138c3b6e8f0146170bb137a86896583a2daf0ce3b3679d07a700006d", - "s": "0x6e407a68dd8b1f51c2e8354a2f2bcc84b5623410ca9c573ef593f3c197bfac9", - "to": "0xd6047245e0fc9baa6231cd8d013b1118b5042aa9", - "transactionIndex": "0x1", - "type": "0x2", - "v": "0x1", - "value": "0x0" - }, - { - "blockHash": "0x7c6bc4bdd2b2b627f1abce0b056a8b2865be7a78135c402247991c74352cb523", - "blockNumber": "0xfed912", - "hash": "0x18b3ea19fb3749bdc8d666f6af0cdfb22f7f0e61bade2505dd0a1b7e6710e75f", - "chainId": "0x1a4", - "from": "0x1f907becd9db9abdcb5a2e9cf8806127f2d8f207", - "gas": "0x21999", - "gasPrice": "0x5f5e132", - "input": "0x04e45aaf000000000000000000000000a2c5a9a5119189d79841e409033acbfb80fd5f680000000000000000000000006abdecfac3e45dd47ec9feffdf8c5d25429bd4ed00000000000000000000000000000000000000000000000000000000000001f40000000000000000000000001f907becd9db9abdcb5a2e9cf8806127f2d8f207000000000000000000000000000000000000000000000000000b1e0f8b94b9ac00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x2746", - "r": "0x6ed46b0339dbecfd7ff19969cca6440a64bd591f0a6f9a259c3539d812b563e0", - "s": "0x2181d166681d9784690fb24be98522b69882facc4e428f30045e4f07af6a4a3a", - "to": "0x19461aab4c4a5afcbf0f4e3055648cb8a0196927", - "transactionIndex": "0x2", - "type": "0x0", - "v": "0x36b", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0x4829a", - "logsBloom": "0x0c000000000000000000000000008800000000100000000000001000200000000000000001000000200000000010000000000000000020000000000000200000000000001000020801000008002000000000001000000002000000000000400000000000020040001044400000000800000000440800000000000010000800000000000000000000000000000001000010000000000000000000000000800000020000000000000000000100000000000800000000008000000000000000000000000002000000000000000000000000000000080000000000000000000020000010000000000000000000000020000020000000008000000000000000000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xe6e5700ce7550f1bd6e1f415db1561a03c1add9f52403933a28034ab4c3779d7", - "nonce": "0x0000000000000000", - "parentHash": "0x99b274f47e55c04dee02571d87a82e514f66228019d6c1b9986da0330fdc21bf", - "receiptsRoot": "0x6accf4b9e6f39afeebd9a8c4ce3b163b43031e8c793a4dcf8b1168810e017e29", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x56d", - "stateRoot": "0x8d3e078068fa62624e2a5098c67a0ad0a9cbae7f8adcb948b35b245d4a4f2f00", - "timestamp": "0x65421c88", - "totalDifficulty": "0x0", - "transactionsRoot": "0x56d229bcf7f1a6055b4c6187731aabbed3aa5ff722d198a94a53ddb56576e435", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed913", - "hash": "0xb2ac49c88c5705c09eec32f6d63177e2e764af8123820e33f38e54e9e8eacb0f", - "transactions": [ - { - "blockHash": "0xb2ac49c88c5705c09eec32f6d63177e2e764af8123820e33f38e54e9e8eacb0f", - "blockNumber": "0xfed913", - "hash": "0x248752c4646ea9114b67556639a27e483cf0b01e5c6173ac66a34726be6b2ab9", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181d0000000000000000000000000000000000000000000000000000000065421c30000000000000000000000000000000000000000000000000000000000000000aec8a872f5ca572df4c7e1989cc99627e0d086fb95f937b6c38ae303affff5cd1000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0ea", - "r": "0x0", - "s": "0x0", - "sourceHash": "0xba15d5caa9ab97e79ef07ba18ba9b363a16c3375a7cf06a1e958edebbb8f6d86", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - }, - { - "blockHash": "0xb2ac49c88c5705c09eec32f6d63177e2e764af8123820e33f38e54e9e8eacb0f", - "blockNumber": "0xfed913", - "hash": "0xae313e7a0b71e44c35437c60fe032eab51384c9c1cae3c921d22a631990abed5", - "accessList": [], - "chainId": "0x1a4", - "from": "0x9cc971e84fe5d09d0967f15ae05dfd553c5a1fa6", - "gas": "0x2ecd4", - "gasPrice": "0x5f5e132", - "input": "0xb630d432000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e05818ed0aa3671b7ea18623aa1e7e4093186e08063ddb2b873c0878d6bacdaa95ff6e3d3466c2e9309600ba08f977fd9f09e64687618949d68e0cd535b73eafc800000000000000000000000000000000000000000000000000000000000ff2d1000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6f7074696d69736d2d676f65726c690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041a3a841b7d7ef9bf0ccdc451d13ed306fc98001ad4d06b3d978a3d7a01fe68c1c4783b8627c56483b311be0ba4eb37239c313348087ca8de5878d6d6849aea7ec1c00000000000000000000000000000000000000000000000000000000000000", - "maxFeePerGas": "0x5f5e164", - "maxPriorityFeePerGas": "0x5f5e100", - "nonce": "0x9ef8a", - "r": "0xda0d4bef1c0b573a1e49d1e3a1ac47c6592c5bd6c6824c3ffac10d21f356c8c0", - "s": "0x6a8eb64f095d749ca3da2502f5d7eb978824142f9dd455258b775630f1e6ef39", - "to": "0xcbbc5da52ea2728279560dca8f4ec08d5f829985", - "transactionIndex": "0x1", - "type": "0x2", - "v": "0x0", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0x39a5c", - "logsBloom": "0x00000000000000000000100000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000001000000000000000000008000000000000000000000000000000000000004000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000008000000000000000000000000000000000000000000000000000000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xe6e5700ce7550f1bd6e1f415db1561a03c1add9f52403933a28034ab4c3779d7", - "nonce": "0x0000000000000000", - "parentHash": "0x7c6bc4bdd2b2b627f1abce0b056a8b2865be7a78135c402247991c74352cb523", - "receiptsRoot": "0x694678e3ead8507c5a04c1384287673b28d2c4b47caa6dbb1db2932c69d4eba6", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x6a3", - "stateRoot": "0x9d96898acaa04128721f0b186824efd293939a7769a68d259513e071dabb5d20", - "timestamp": "0x65421c8a", - "totalDifficulty": "0x0", - "transactionsRoot": "0xa2429aee09f470ea3e73196f3faeec5f528996893af132a9cd18ed0dfd15a167", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed914", - "hash": "0xe2fcad9b10fd668b0a3a05e1ba1437e4730b4b4c123474db58824cbce0473f19", - "transactions": [ - { - "blockHash": "0xe2fcad9b10fd668b0a3a05e1ba1437e4730b4b4c123474db58824cbce0473f19", - "blockNumber": "0xfed914", - "hash": "0x77fcd6bfe922737d5d18b673490cf42fe7e6d8e1d0b25f24accaf7b69d0a3b38", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181d0000000000000000000000000000000000000000000000000000000065421c30000000000000000000000000000000000000000000000000000000000000000aec8a872f5ca572df4c7e1989cc99627e0d086fb95f937b6c38ae303affff5cd1000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0eb", - "r": "0x0", - "s": "0x0", - "sourceHash": "0x6ad54a0f7c8ec4e730a1c76339c13a30f1183f942d190013f652469177af34b3", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0xb711", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xe6e5700ce7550f1bd6e1f415db1561a03c1add9f52403933a28034ab4c3779d7", - "nonce": "0x0000000000000000", - "parentHash": "0xb2ac49c88c5705c09eec32f6d63177e2e764af8123820e33f38e54e9e8eacb0f", - "receiptsRoot": "0x29079b696c12a19999f3bb303fddb6fc12fb701f427678cca24954b91080ada3", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x365", - "stateRoot": "0x9c89eda07d01df4cd74e68c93249e8c535923b9f62db92a2eb65eec134b472d9", - "timestamp": "0x65421c8c", - "totalDifficulty": "0x0", - "transactionsRoot": "0x9087ac2ebd3f514d129a61ec1dc59f9d53d008f567635ea6dcc6b4d17a38521c", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed915", - "hash": "0x9b1591a52a7ad4a27b67db3b58c9e85242eb2903f9009087e95d27916517addf", - "transactions": [ - { - "blockHash": "0x9b1591a52a7ad4a27b67db3b58c9e85242eb2903f9009087e95d27916517addf", - "blockNumber": "0xfed915", - "hash": "0xefdd5e3cb0c42cd6490c46e4df90a42aa39d1accaa201b1ff3ebfdd0041f8878", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181e0000000000000000000000000000000000000000000000000000000065421c3c000000000000000000000000000000000000000000000000000000000000000a0442372046dcf86bdb03203ea1a9c8f62053f3cb9e7c488c0228a49a393387d900000000000000000000000000000000000000000000000000000000000000000000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0ec", - "r": "0x0", - "s": "0x0", - "sourceHash": "0x569fdc44663d5ff3e34f4bb1362b745e12baa9947afcf6d9685cb19e4a328932", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0xba25", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xbc2f59d9f90644e2b29cd5b49fa4f15b99d4b4254ca1250a67e9922c69e3071b", - "nonce": "0x0000000000000000", - "parentHash": "0xe2fcad9b10fd668b0a3a05e1ba1437e4730b4b4c123474db58824cbce0473f19", - "receiptsRoot": "0x030b2afe4ffa211c38dc7bd40db30e3d64b2f8463e24ff7423a3bb84ba449a47", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x365", - "stateRoot": "0xcb5dff8eab1c744c5ee14a21e3ed884576422d157234fc0e9e5fdae97ef1e20d", - "timestamp": "0x65421c8e", - "totalDifficulty": "0x0", - "transactionsRoot": "0xf69f6e20b6133fca5c01bccd9cc50408323316bb4518ccc3caaf1ee8b8c6d399", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed916", - "hash": "0x1fe58ee6c851316735107797621fcc3f942c70d82d1941dea4aa8d5ff2df8c06", - "transactions": [ - { - "blockHash": "0x1fe58ee6c851316735107797621fcc3f942c70d82d1941dea4aa8d5ff2df8c06", - "blockNumber": "0xfed916", - "hash": "0xae840243a0d83b5c65a8a86ead3add0bff61f6be83a5f6f2e030b8415438e611", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181e0000000000000000000000000000000000000000000000000000000065421c3c000000000000000000000000000000000000000000000000000000000000000a0442372046dcf86bdb03203ea1a9c8f62053f3cb9e7c488c0228a49a393387d900000000000000000000000000000000000000000000000000000000000000010000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0ed", - "r": "0x0", - "s": "0x0", - "sourceHash": "0x796fb268a12038af3422b4f479d14ba9de39e9615fc312a70f2c6f72ed40bef2", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - }, - { - "blockHash": "0x1fe58ee6c851316735107797621fcc3f942c70d82d1941dea4aa8d5ff2df8c06", - "blockNumber": "0xfed916", - "hash": "0xa7d6059a2f4b1315ea78b3130e6d017e161dca675bbf604cacc8ac566297bb27", - "accessList": [], - "chainId": "0x1a4", - "from": "0x9cc971e84fe5d09d0967f15ae05dfd553c5a1fa6", - "gas": "0x2ecd4", - "gasPrice": "0x5f5e132", - "input": "0xb630d432000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e0ff6e3d3466c2e9309600ba08f977fd9f09e64687618949d68e0cd535b73eafc81ae24f324b0592e76de47f8c55800c25ee4415ee6a518adf0ad07c243582b94e00000000000000000000000000000000000000000000000000000000000ff2d2000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6f7074696d69736d2d676f65726c6900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000417dbc074ecf060a633a12249bfa92b97350f1e8e6dcbe2a3654edc7ed08da3ca436d29cb831469eb85874679611e41af5c62ab61a300a400ca82fa07def0d2df81c00000000000000000000000000000000000000000000000000000000000000", - "maxFeePerGas": "0x5f5e164", - "maxPriorityFeePerGas": "0x5f5e100", - "nonce": "0x9ef8b", - "r": "0xe47ed7ece99e49cd04581cbacf95639eea6bf5742ccc253730e6b7c5d103a069", - "s": "0x2665dad7ccb36e22b33ef69560ba7fc03b6444607f524163721298be4fad2cd1", - "to": "0xcbbc5da52ea2728279560dca8f4ec08d5f829985", - "transactionIndex": "0x1", - "type": "0x2", - "v": "0x1", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0x3dd28", - "logsBloom": "0x00000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000401000000000000000000000000000000000000000000000000000000000004000000000010000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000800000002000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xbc2f59d9f90644e2b29cd5b49fa4f15b99d4b4254ca1250a67e9922c69e3071b", - "nonce": "0x0000000000000000", - "parentHash": "0x9b1591a52a7ad4a27b67db3b58c9e85242eb2903f9009087e95d27916517addf", - "receiptsRoot": "0xe06c4e45b93e20b7d9a49c424b0847b86aa72a21bb63c51e6d8ff7adef255edb", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x6a3", - "stateRoot": "0xffae2b813a5569a870ad07110e0e441ba496fbcea05ecb391f912c9b2dcf152e", - "timestamp": "0x65421c90", - "totalDifficulty": "0x0", - "transactionsRoot": "0xc425731c403af080ea2c24a7ed00788e4a5100535f1bcf2e00180e5b583b9377", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed917", - "hash": "0xd72d6a9c21ffc5571367a2985d0196869546fd2a9cb654ccc5c306de94d7227e", - "transactions": [ - { - "blockHash": "0xd72d6a9c21ffc5571367a2985d0196869546fd2a9cb654ccc5c306de94d7227e", - "blockNumber": "0xfed917", - "hash": "0xeef7d113480059eb79a2a300e6000214be56c7fdbd03446221137c55a96d86ea", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181e0000000000000000000000000000000000000000000000000000000065421c3c000000000000000000000000000000000000000000000000000000000000000a0442372046dcf86bdb03203ea1a9c8f62053f3cb9e7c488c0228a49a393387d900000000000000000000000000000000000000000000000000000000000000020000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0ee", - "r": "0x0", - "s": "0x0", - "sourceHash": "0xa3dfd244a67e69fee01d3ced68368314efcb2323fc5c4632b50d40eda11ca0ef", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0xb711", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xbc2f59d9f90644e2b29cd5b49fa4f15b99d4b4254ca1250a67e9922c69e3071b", - "nonce": "0x0000000000000000", - "parentHash": "0x1fe58ee6c851316735107797621fcc3f942c70d82d1941dea4aa8d5ff2df8c06", - "receiptsRoot": "0x29079b696c12a19999f3bb303fddb6fc12fb701f427678cca24954b91080ada3", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x365", - "stateRoot": "0x159d678d0baf9cce807b46f9c1c9f1a0740d08dad6441852f04cabcbfb3415b0", - "timestamp": "0x65421c92", - "totalDifficulty": "0x0", - "transactionsRoot": "0xc1ec6ee4c4d144bea0937dbf26b2b97a3e94e9b885a74fd1f48cce3d987a5d3e", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed918", - "hash": "0x9c488b92e950d555f0647fb12763b9fabe8216018ee23417ac011f80ced40e1b", - "transactions": [ - { - "blockHash": "0x9c488b92e950d555f0647fb12763b9fabe8216018ee23417ac011f80ced40e1b", - "blockNumber": "0xfed918", - "hash": "0x7ea703c53e548e01eb103a4aaa2e249d74dcbc20d7645d0f3a1337a7a1ab6d12", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181e0000000000000000000000000000000000000000000000000000000065421c3c000000000000000000000000000000000000000000000000000000000000000a0442372046dcf86bdb03203ea1a9c8f62053f3cb9e7c488c0228a49a393387d900000000000000000000000000000000000000000000000000000000000000030000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0ef", - "r": "0x0", - "s": "0x0", - "sourceHash": "0xe55bccba45b06e900b30fd409cdacf4e5d0dded19020160afbb083db3afa55e6", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - }, - { - "blockHash": "0x9c488b92e950d555f0647fb12763b9fabe8216018ee23417ac011f80ced40e1b", - "blockNumber": "0xfed918", - "hash": "0xca5b9eb4c9a284a8a84396f4dc0b3326955f5c73ed62a9daebbb4b38f0c2716d", - "accessList": [], - "chainId": "0x1a4", - "from": "0xb0c0f73f84ce7355e755846c123f0a5848304b52", - "gas": "0xf4240", - "gasPrice": "0x9502f932", - "input": "0x1249c58b", - "maxFeePerGas": "0x9502f964", - "maxPriorityFeePerGas": "0x9502f900", - "nonce": "0x3", - "r": "0xd4ba36ff1a40f547cde39e29dab6fb6e0390eab475500e489da0ac611346c762", - "s": "0x680a832bc607039b0d413d47ed88acdb0adce892bb84ffe9f802fcaeb0516c1d", - "to": "0x222e406c60dcda91e688afadbad5742c858e57a0", - "transactionIndex": "0x1", - "type": "0x2", - "v": "0x1", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0x488e4", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000040000000030000000000000000000800000000000000000000000010000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000002000000000000000000000000000000000000000000000000000020000000000000000080000000000020000400010000000000000000000000800000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xbc2f59d9f90644e2b29cd5b49fa4f15b99d4b4254ca1250a67e9922c69e3071b", - "nonce": "0x0000000000000000", - "parentHash": "0xd72d6a9c21ffc5571367a2985d0196869546fd2a9cb654ccc5c306de94d7227e", - "receiptsRoot": "0x537ebf10286b3c4b59b10c4afc279793d83f0cd2a343a3d06f25cfe32e0f0968", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x3dc", - "stateRoot": "0x4071aba551a787714d201fb571f41bb50f6c9c781732b2941c0e217b7a3faa73", - "timestamp": "0x65421c94", - "totalDifficulty": "0x0", - "transactionsRoot": "0xa843d6badf95772204013b016d39ce174ff91ae3607d089d3e165e195572d4ac", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed919", - "hash": "0xd1716b8667d686feaa8ffcb0c923dc56f6447148d38981e63d3b40ac7a470ea4", - "transactions": [ - { - "blockHash": "0xd1716b8667d686feaa8ffcb0c923dc56f6447148d38981e63d3b40ac7a470ea4", - "blockNumber": "0xfed919", - "hash": "0xe90fe348493e03702246824a1b6a03bf75fa208c1a6270dba25c5d2d22b06d78", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181e0000000000000000000000000000000000000000000000000000000065421c3c000000000000000000000000000000000000000000000000000000000000000a0442372046dcf86bdb03203ea1a9c8f62053f3cb9e7c488c0228a49a393387d900000000000000000000000000000000000000000000000000000000000000040000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0f0", - "r": "0x0", - "s": "0x0", - "sourceHash": "0x9e8b5939cdaf21d9d5ad318d9efeaa92f4c986807a9a8dc084d40beba403040b", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - }, - { - "blockHash": "0xd1716b8667d686feaa8ffcb0c923dc56f6447148d38981e63d3b40ac7a470ea4", - "blockNumber": "0xfed919", - "hash": "0xe6b258034c09860a5db34235fadb0001274a7185e2622e96ac24561599917531", - "accessList": [], - "chainId": "0x1a4", - "from": "0x9cc971e84fe5d09d0967f15ae05dfd553c5a1fa6", - "gas": "0x2ece0", - "gasPrice": "0x5f5e132", - "input": "0xb630d432000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e01ae24f324b0592e76de47f8c55800c25ee4415ee6a518adf0ad07c243582b94ea350f21aaefb7c3df254e3576b1bdfdd3def52dd4c9531d90bd5185cf8ecd70f00000000000000000000000000000000000000000000000000000000000ff2d3000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6f7074696d69736d2d676f65726c690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000041ebd74b75f22eb0fe52f60dc86ff614a6b432a41769b5b73b5996070aee15fb921b4e6d9d0295fbea680dce7b984ce7c558559e2b4b7a460a9b7734b539fa5df61b00000000000000000000000000000000000000000000000000000000000000", - "maxFeePerGas": "0x5f5e164", - "maxPriorityFeePerGas": "0x5f5e100", - "nonce": "0x9ef8c", - "r": "0x685b5ea55e71d595eb71db6df7a6a8c9b923da8990e101fefaf96ea8bc845afc", - "s": "0x7bef0a51440770c2d50d465c7e5a636c69075525c424fb128c2c76929523df4f", - "to": "0xcbbc5da52ea2728279560dca8f4ec08d5f829985", - "transactionIndex": "0x1", - "type": "0x2", - "v": "0x0", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0x39a68", - "logsBloom": "0x00000000000000000000100004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000004000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000002000000000000000800000000000000000000000000000000000000000000000000000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xbc2f59d9f90644e2b29cd5b49fa4f15b99d4b4254ca1250a67e9922c69e3071b", - "nonce": "0x0000000000000000", - "parentHash": "0x9c488b92e950d555f0647fb12763b9fabe8216018ee23417ac011f80ced40e1b", - "receiptsRoot": "0x41591a6b43215d57424783f0e7e8243015b2f0daf24871d362d5d2f409430773", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x6a3", - "stateRoot": "0x387d78e93b05129115d723b444e16dc0f248d1d537b4714a3a3a9cabd7f43d2f", - "timestamp": "0x65421c96", - "totalDifficulty": "0x0", - "transactionsRoot": "0x4d11910e0a7c63816ae047c748b80d2c5f30d0cf9cf47265a797b1e1e1d53ebe", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed91a", - "hash": "0x996594979c173d1bd6828fd1e90d3e00579e71bc71de6ad236977dae87953c2f", - "transactions": [ - { - "blockHash": "0x996594979c173d1bd6828fd1e90d3e00579e71bc71de6ad236977dae87953c2f", - "blockNumber": "0xfed91a", - "hash": "0xc9cd1bedc970df025de79bfa8085a37dd269c0f88a26a00df1ef836e36a87995", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181e0000000000000000000000000000000000000000000000000000000065421c3c000000000000000000000000000000000000000000000000000000000000000a0442372046dcf86bdb03203ea1a9c8f62053f3cb9e7c488c0228a49a393387d900000000000000000000000000000000000000000000000000000000000000050000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0f1", - "r": "0x0", - "s": "0x0", - "sourceHash": "0x7233d5ed50fea38f56f840e94adb6e429b020b8b6da71cbbfc25bec3d0356d1a", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - }, - { - "blockHash": "0x996594979c173d1bd6828fd1e90d3e00579e71bc71de6ad236977dae87953c2f", - "blockNumber": "0xfed91a", - "hash": "0x6d2166d3ada90c91433740c3d373c1d9657271a31e132768855b618a17a7ed46", - "accessList": [], - "chainId": "0x1a4", - "from": "0x1307ab404e65818318f9590ffd63ea8ff1720c8a", - "gas": "0x14fba", - "gasPrice": "0x59682f32", - "input": "0xde2996cb0000000000000000000000000000000000000000000000000000000000003175000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000090000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000f4126322c4226322c4426322c4326320000000000000000000000000000000000", - "maxFeePerGas": "0x59682f3c", - "maxPriorityFeePerGas": "0x59682f00", - "nonce": "0x48", - "r": "0xaa597cc03c45f83a68a3f0e439be15be319a99085daa7a062c1b91b0d2664852", - "s": "0x3588f498d983d1ddb716ff098904365401481c702674057d06ab836cd2395078", - "to": "0xfaea5cd610bd946cfdaf83d023280eca35d4fed9", - "transactionIndex": "0x1", - "type": "0x2", - "v": "0x0", - "value": "0x0" - }, - { - "blockHash": "0x996594979c173d1bd6828fd1e90d3e00579e71bc71de6ad236977dae87953c2f", - "blockNumber": "0xfed91a", - "hash": "0xf0855b0dbcd30793683551f2fd679c1bb800f64b317b9b9eac96f7f0a3ac3475", - "chainId": "0x1a4", - "from": "0x1f907becd9db9abdcb5a2e9cf8806127f2d8f207", - "gas": "0x2196d", - "gasPrice": "0x5f5e132", - "input": "0x04e45aaf000000000000000000000000d82378800bb914f25bd7e438e205ac066ce22b000000000000000000000000006abdecfac3e45dd47ec9feffdf8c5d25429bd4ed00000000000000000000000000000000000000000000000000000000000001f40000000000000000000000001f907becd9db9abdcb5a2e9cf8806127f2d8f20700000000000000000000000000000000000000000000000000017df8bb1016ae00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "nonce": "0x2747", - "r": "0x57ab0acfd21be659b595f0cb75dfa8b9c9dd972431e95938d3b3b4c59a111555", - "s": "0x363fa14f861bab64b28eab81ec71eb5d5dd31e38251a5fb9c0c19d6b929e6b2a", - "to": "0x19461aab4c4a5afcbf0f4e3055648cb8a0196927", - "transactionIndex": "0x2", - "type": "0x0", - "v": "0x36c", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0x3b253", - "logsBloom": "0x08000010000000000000800000000000000000100000000800000000000008000000000000000000000000000000000000000000000020000080000000200000000000400200000800000408000000000000000000002002000000000000000000000000000000000044400000000080010000400000000000000010000800000000000000000000000000000001000000000000000000000000000000004000020000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000010000000080000000000000000000000002010002000000000000000000000000000000000000000000000000000000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0xbc2f59d9f90644e2b29cd5b49fa4f15b99d4b4254ca1250a67e9922c69e3071b", - "nonce": "0x0000000000000000", - "parentHash": "0xd1716b8667d686feaa8ffcb0c923dc56f6447148d38981e63d3b40ac7a470ea4", - "receiptsRoot": "0xa5cf1ccd212328bb2b60a0bc6a1de6f4263535c5665e3c3dd620b91a658e77e3", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x5ef", - "stateRoot": "0x09668a27a6d3054f2f29343bae20dd0fd5c4b957773ca2273d694cf09c93067a", - "timestamp": "0x65421c98", - "totalDifficulty": "0x0", - "transactionsRoot": "0x660784e7e1b133c8132173c5065b88d62a2442eb737f0b9827b15bb1dcb62ed6", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed91b", - "hash": "0xc667c769f4ab49d08b7ed565e5df1367028d1553e3584f0c7daf510dc3e4d67e", - "transactions": [ - { - "blockHash": "0xc667c769f4ab49d08b7ed565e5df1367028d1553e3584f0c7daf510dc3e4d67e", - "blockNumber": "0xfed91b", - "hash": "0x9d138a866cb3a47e176fdeb5382b26fb22a1e52c60d8e6c6124cc4779821da09", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181f0000000000000000000000000000000000000000000000000000000065421c48000000000000000000000000000000000000000000000000000000000000000a0a2cf2dc6b0e57d45fbcb949511d0fa42cd13b361d55b8cf46ffc2b05e1b186400000000000000000000000000000000000000000000000000000000000000000000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0f2", - "r": "0x0", - "s": "0x0", - "sourceHash": "0x0faea38d53b0a34261344968a4ada77d2edf44169a63c821bf0e3a5a180f5be9", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - }, - { - "blockHash": "0xc667c769f4ab49d08b7ed565e5df1367028d1553e3584f0c7daf510dc3e4d67e", - "blockNumber": "0xfed91b", - "hash": "0x4ebb88f593e4fb546ded00cf2d59b95cac2571b7ff75ba66520d39c593a83ee7", - "accessList": [], - "chainId": "0x1a4", - "from": "0xb3311bf816cc744a86645e52a0b9d41521d0ab5c", - "gas": "0x7a120", - "gasPrice": "0x7270e3c", - "input": "0xc9807539000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000020001010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000025e5cfbea6f68c0eb25a0cf643facd9e00092441030300010200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000007f216900000000000000000000000000000000000000000000000000000000007f4f7480000000000000000000000000000000000000000000000000000000007f4f7480000000000000000000000000000000000000000000000000000000007f4f74800000000000000000000000000000000000000000000000000000000000000027be52e3ae6f5d06f3c366664e1d3ecdf52c6c5d556d1ac8b6fd8debc84101f5a6175f6fbcdd7ac0319b1d6894e1a20a40e59ed30a8f94d8c67e301cff4ff3906000000000000000000000000000000000000000000000000000000000000000225460ca4e9545f97e9a8d7298a77dcef503c346973ba652f81b0946ac9a249f36ae40a70f603075cc043f7143a679edfea3e39a6e8c1333a3f4731ec3221b255", - "maxFeePerGas": "0x7270e5a", - "maxPriorityFeePerGas": "0x7270e0a", - "nonce": "0x758a7", - "r": "0x72bc3984839f2a07d35932f6c1c404b008e61ededd608adf9cb1f9743040bd1e", - "s": "0x6beca1f146cc4bb73ad4b3aaa5d0cfe3c54c10f81ac95eb4e5a64abbe9f89989", - "to": "0xd4cc45b63283ec8e80cdce3632cb8ffa36d52894", - "transactionIndex": "0x1", - "type": "0x2", - "v": "0x1", - "value": "0x0" - }, - { - "blockHash": "0xc667c769f4ab49d08b7ed565e5df1367028d1553e3584f0c7daf510dc3e4d67e", - "blockNumber": "0xfed91b", - "hash": "0x4e5a5289f3313a4f243c4f317247ea50fa41545da86b9fd06808b001dd210e0a", - "accessList": [], - "chainId": "0x1a4", - "from": "0x9cc971e84fe5d09d0967f15ae05dfd553c5a1fa6", - "gas": "0x2ece0", - "gasPrice": "0x5f5e132", - "input": "0xb630d432000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000e0a350f21aaefb7c3df254e3576b1bdfdd3def52dd4c9531d90bd5185cf8ecd70f4c79171ea93af9cef995c9330c5cadff2c0bafc145f95c4be9b427ccc4f8a27e00000000000000000000000000000000000000000000000000000000000ff2d4000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f6f7074696d69736d2d676f65726c69000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004148d182eb4232d8bd0f5560fd62e47502ab22d29de4d26d30226689cbcf8714f419594d06c45f412b8cf6e0116be70db22226635bc20ecdf98bd2da49f64501f11c00000000000000000000000000000000000000000000000000000000000000", - "maxFeePerGas": "0x5f5e164", - "maxPriorityFeePerGas": "0x5f5e100", - "nonce": "0x9ef8d", - "r": "0x9f63feaa1f048fbe5cbe432c0e4a52e4d0ab760e58ae8a13477018b3d949bdb6", - "s": "0x288093ef80611952b5b72cee620b418e5f1d73e862aed63100da7e837b066d45", - "to": "0xcbbc5da52ea2728279560dca8f4ec08d5f829985", - "transactionIndex": "0x2", - "type": "0x2", - "v": "0x0", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0x58af2", - "logsBloom": "0x00008000002000000000100000000000000000000000000000000000004000000000300000000000000000000000000000000000000200000000000080000000000000000000000000000001002000000000000001001000000000000000000000080000020000000000000000000800000000200000000000002000000001000000000008000000000000000001000000000480000000000000000004000000000010001000001000000000000000000000000000000000000000000000000000000000000000000010000000000000004000000000000000000002000020000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0x6c3f2a849b90f4902a13f0a1cb7aabdbfd94754d9fcc1c3e006f3198c78a62b7", - "nonce": "0x0000000000000000", - "parentHash": "0x996594979c173d1bd6828fd1e90d3e00579e71bc71de6ad236977dae87953c2f", - "receiptsRoot": "0xe1e140c9522914486c0338f4022999fd1940ef448d8b709d8431fd6c5729a4bb", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x980", - "stateRoot": "0xd3b3b007c6f83779866dc76162ad899c0a283a823d12f53572a0cfad49f03c2e", - "timestamp": "0x65421c9a", - "totalDifficulty": "0x0", - "transactionsRoot": "0x367c99573f2dabf29aae707b0a334e768e0167f463e12ea0e6a699b5a9fbcb29", - "uncles": [], - "baseFeePerGas": "0x32" - }, - { - "number": "0xfed91c", - "hash": "0x677035e9924cf523dea9a5b5bdf58bbb5e670670c9d4c34d1104b8f51145b138", - "transactions": [ - { - "blockHash": "0x677035e9924cf523dea9a5b5bdf58bbb5e670670c9d4c34d1104b8f51145b138", - "blockNumber": "0xfed91c", - "hash": "0x43f734f9a9cc309f305eb5c9e98a8645bb271255c74fc91b141e1edb7987b2cc", - "from": "0xdeaddeaddeaddeaddeaddeaddeaddeaddead0001", - "gas": "0xf4240", - "gasPrice": "0x0", - "input": "0x015d8eb9000000000000000000000000000000000000000000000000000000000098181f0000000000000000000000000000000000000000000000000000000065421c48000000000000000000000000000000000000000000000000000000000000000a0a2cf2dc6b0e57d45fbcb949511d0fa42cd13b361d55b8cf46ffc2b05e1b186400000000000000000000000000000000000000000000000000000000000000010000000000000000000000007431310e026b69bfc676c0013e12a1a11411eec9000000000000000000000000000000000000000000000000000000000000083400000000000000000000000000000000000000000000000000000000000f4240", - "mint": "0x0", - "nonce": "0xc0e0f3", - "r": "0x0", - "s": "0x0", - "sourceHash": "0xd2e9ac342752449811c4e4cff763603c3045d91149a4a448ebb1bba0f0427cea", - "to": "0x4200000000000000000000000000000000000015", - "transactionIndex": "0x0", - "type": "0x7e", - "v": "0x0", - "value": "0x0" - } - ], - "difficulty": "0x0", - "extraData": "0x", - "gasLimit": "0x2faf080", - "gasUsed": "0xf9dd", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "miner": "0x4200000000000000000000000000000000000011", - "mixHash": "0x6c3f2a849b90f4902a13f0a1cb7aabdbfd94754d9fcc1c3e006f3198c78a62b7", - "nonce": "0x0000000000000000", - "parentHash": "0xc667c769f4ab49d08b7ed565e5df1367028d1553e3584f0c7daf510dc3e4d67e", - "receiptsRoot": "0x77ddca50217671904c60e97a070a82ede75581f477f7c49fadd91214e7091ae6", - "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "size": "0x365", - "stateRoot": "0x6f72537a7a8ff9d4b3d747902924015e36dc947ac10b402f9d5c8ffe15393b2c", - "timestamp": "0x65421c9c", - "totalDifficulty": "0x0", - "transactionsRoot": "0x62c96bb38b6084a0eaf88121d99fa1610cec92c7fe4a027567e5407dc4b18935", - "uncles": [], - "baseFeePerGas": "0x32" - } -] \ No newline at end of file diff --git a/hildr-proposer/build.gradle b/hildr-proposer/build.gradle deleted file mode 100644 index 4ce6a22e..00000000 --- a/hildr-proposer/build.gradle +++ /dev/null @@ -1,256 +0,0 @@ -plugins { - id 'java' - id 'application' - id "jacoco" - id "com.diffplug.spotless" version "6.22.0" - id "net.ltgt.errorprone" version "3.1.0" - id 'com.github.johnrengelman.shadow' version '8.1.1' -} - -group = 'io.optimism' -version = '0.4.4' - -repositories { - // Use Maven Central for resolving dependencies. - mavenCentral() - maven { - url "https://artifacts.consensys.net/public/teku/maven/" - } - maven { - url "https://dl.cloudsmith.io/public/libp2p/jvm-libp2p/maven/" - } - maven { - url "https://hyperledger.jfrog.io/artifactory/besu-maven/" - } - maven { - url "https://artifacts.consensys.net/public/maven/maven/" - } - maven { url "https://jitpack.io" } - google() -} - -application { - // Define the main class for the application. - mainClass = 'io.optimism.proposer.HildrProposer' -} - -tasks.withType(JavaCompile).configureEach { - options.annotationProcessorPath = configurations.annotationProcessor - options.compilerArgs += "--enable-preview" - options.compilerArgs += "-Xlint:preview" - options.compilerArgs += ["-Aproject=${project.group}/${project.name}"] -} - -tasks.withType(JavaCompile).configureEach { - options.annotationProcessorPath = configurations.annotationProcessor - options.compilerArgs += "--enable-preview" - options.compilerArgs += "-Xlint:preview" - options.compilerArgs += ["-Aproject=${project.group}/${project.name}"] -} - -tasks.withType(Test).configureEach { - jvmArgs += "--enable-preview" -} - -tasks.withType(JavaExec).configureEach { - jvmArgs += "--enable-preview" -} - -dependencies { - implementation project(':hildr-utilities') - implementation 'com.github.gestalt-config:gestalt-core:0.20.4' - implementation 'com.github.gestalt-config:gestalt-toml:0.20.4' - - implementation 'com.fasterxml.jackson:jackson-bom:2.15.2' - implementation 'com.fasterxml.jackson.core:jackson-core' - implementation 'com.fasterxml.jackson.dataformat:jackson-dataformat-toml' - implementation 'org.jctools:jctools-core:4.0.1' - - implementation 'io.jsonwebtoken:jjwt-api:0.11.5' - implementation 'io.jsonwebtoken:jjwt-impl:0.11.5' - implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5' - - //jsonrpc - implementation('io.vertx:vertx-auth-jwt:4.4.2') - implementation('io.vertx:vertx-core:4.4.2') - implementation('io.vertx:vertx-web:4.4.2') - - implementation 'io.micrometer:micrometer-registry-prometheus:1.11.0' - implementation platform('io.micrometer:micrometer-tracing-bom:1.1.1') - implementation 'io.micrometer:micrometer-tracing' - implementation 'io.micrometer:micrometer-tracing-bridge-otel' - - // Logback - implementation 'ch.qos.logback:logback-core:1.4.12' - implementation 'ch.qos.logback:logback-classic:1.4.14' - implementation 'org.slf4j:slf4j-api:2.0.7' - - implementation platform("io.opentelemetry:opentelemetry-bom-alpha:1.26.0-alpha") - // OpenTelemetry core - implementation(platform("io.opentelemetry:opentelemetry-bom:1.26.0")) - implementation 'io.opentelemetry:opentelemetry-api' - implementation 'io.opentelemetry:opentelemetry-sdk' - implementation 'io.opentelemetry:opentelemetry-sdk-logs' - - // OpenTelemetry log4j appenders - implementation platform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:1.26.0-alpha") - runtimeOnly 'io.opentelemetry.instrumentation:opentelemetry-logback-mdc-1.0' - - implementation('io.tmio:tuweni-crypto:2.4.2'){ - exclude group: 'org.bouncycastle', module: 'bcprov-jdk15on' - exclude group: 'org.apache.tuweni', module: 'tuweni-bytes' - exclude group: 'org.apache.tuweni', module: 'tuweni-units' - exclude group: 'org.apache.tuweni', module: 'tuweni-rlp' - exclude group: 'org.apache.tuweni', module: 'tuweni-crypto' - } - - implementation 'info.picocli:picocli:4.7.3' - annotationProcessor 'info.picocli:picocli-codegen:4.7.3' - - implementation 'io.tmio:tuweni-crypto:2.4.2' - - // Use JUnit Jupiter for testing. - testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0' - // https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite-api - testImplementation 'org.junit.platform:junit-platform-suite-api:1.9.1' - // https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite-engine - testRuntimeOnly 'org.junit.platform:junit-platform-suite-engine:1.9.1' - - testRuntimeOnly 'org.junit.platform:junit-platform-reporting:1.9.1' - - testImplementation 'org.mockito:mockito-junit-jupiter:2.19.0' - testImplementation("com.squareup.okhttp3:mockwebserver:5.0.0-alpha.14") - - errorprone("com.google.errorprone:error_prone_core:2.18.0") -} - -// Apply a specific Java toolchain to ease working on different environments. -java { - toolchain { - languageVersion = JavaLanguageVersion.of(21) - } -} - -test { - useJUnitPlatform() - testLogging { - events "passed", "skipped", "failed" - } - finalizedBy jacocoTestReport -} - -jacoco { - toolVersion = "0.8.12" -} - -jacocoTestReport { - dependsOn test - - reports { - csv.required = true - } -} - -jacocoTestCoverageVerification { - violationRules { - rule { - limit { - minimum = 0 - } - } - } -} - -spotless { - // optional: limit format enforcement to just the files changed by this feature branch -// ratchetFrom 'origin/main' - - format 'misc', { - // define the files to apply `misc` to - target '*.gradle', '*.md', '.gitignore' - - // define the steps to apply to those files - trimTrailingWhitespace() - indentWithTabs() // or spaces. Takes an integer argument if you don't like 4 - endWithNewline() - } - java { - // Use the default importOrder configuration - - // don't need to set target, it is inferred from java - - // apply a specific flavor of google-java-format - palantirJavaFormat('2.38.0') - // fix formatting of type annotations - formatAnnotations() - - importOrder() - - removeUnusedImports() - } -} - -tasks.named('test') { - // Use JUnit Platform for unit tests. - useJUnitPlatform() -} - -check { - dependsOn += jacocoTestCoverageVerification -// dependsOn += integrationTest -} - -tasks.withType(Test).configureEach { - def outputDir = reports.junitXml.outputLocation - jvmArgumentProviders << ({ - [ - "-Djunit.platform.reporting.open.xml.enabled=true", - "-Djunit.platform.reporting.output.dir=${outputDir.get().asFile.absolutePath}", - "--enable-preview" - ] - } as CommandLineArgumentProvider) -} - -java { - withJavadocJar() - withSourcesJar() -} - - -javadoc { - if (JavaVersion.current().isJava9Compatible()) { - options.addBooleanOption('html5', true) - } - options.addBooleanOption('-enable-preview', true) - options.addStringOption('-release', '21') -} - -jar { - enabled = false - manifest { - attributes "Main-Class": "io.optimism.proposer.HildrProposer" - attributes "Multi-Release": "true" - } - dependsOn(shadowJar) -} - -shadowJar { - archiveFileName = "${project.name}-${project.version}.jar" - transform(com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer) -} - -task buildJarForDocker { - dependsOn jar - def buildImageDir = "build/docker" - def out = new ByteArrayOutputStream() - doFirst { - new File(buildImageDir).mkdirs() - copy { - from "build/libs/${project.name}-${project.version}.jar" - into buildImageDir - rename "${project.name}-${project.version}.jar", "${project.name}.jar" - } - } - println(out.toString()) -} diff --git a/hildr-proposer/src/main/java/io/optimism/proposer/HildrProposer.java b/hildr-proposer/src/main/java/io/optimism/proposer/HildrProposer.java deleted file mode 100644 index 4e4052e1..00000000 --- a/hildr-proposer/src/main/java/io/optimism/proposer/HildrProposer.java +++ /dev/null @@ -1,26 +0,0 @@ -package io.optimism.proposer; - -import io.optimism.proposer.cli.Cli; -import picocli.CommandLine; - -/** - * Batcher main method. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class HildrProposer { - - /** Constructor of HildrBatcher. */ - public HildrProposer() {} - - /** - * Main method of HildrBatcher. - * - * @param args Starts arguments - */ - public static void main(String[] args) { - int exitCode = new CommandLine(new Cli()).execute(args); - System.exit(exitCode); - } -} diff --git a/hildr-proposer/src/main/java/io/optimism/proposer/L2OutputSubmitter.java b/hildr-proposer/src/main/java/io/optimism/proposer/L2OutputSubmitter.java deleted file mode 100644 index 7eac02d0..00000000 --- a/hildr-proposer/src/main/java/io/optimism/proposer/L2OutputSubmitter.java +++ /dev/null @@ -1,232 +0,0 @@ -package io.optimism.proposer; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.util.concurrent.AbstractExecutionThreadService; -import io.optimism.proposer.config.Config; -import io.optimism.proposer.exception.OutputSubmitterExecution; -import io.optimism.utilities.rpc.Web3jProvider; -import io.optimism.utilities.rpc.response.OutputRootResult; -import io.optimism.utilities.rpc.response.SyncStatusResult; -import io.optimism.utilities.telemetry.TracerTaskWrapper; -import io.optimism.utilities.web3j.Web3jUtil; -import java.io.IOException; -import java.math.BigInteger; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.StructuredTaskScope; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.web3j.abi.FunctionEncoder; -import org.web3j.abi.datatypes.Function; -import org.web3j.abi.datatypes.Type; -import org.web3j.abi.datatypes.generated.Uint256; -import org.web3j.crypto.Credentials; -import org.web3j.crypto.RawTransaction; -import org.web3j.protocol.Web3j; -import org.web3j.protocol.Web3jService; -import org.web3j.protocol.core.Request; -import org.web3j.protocol.core.methods.response.TransactionReceipt; -import org.web3j.protocol.core.methods.response.Web3Sha3; -import org.web3j.utils.Numeric; - -/** - * L2OutputSubmitter submits L2 output. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class L2OutputSubmitter extends AbstractExecutionThreadService { - - private static final Logger LOGGER = LoggerFactory.getLogger(L2OutputSubmitter.class); - - private final Config config; - private final Web3j l1Client; - private final Web3j l2Client; - private final Credentials l2From; - private final Web3jService rollUpClient; - private final ObjectMapper mapper; - - private BigInteger nonce; - private volatile boolean isShutdownTriggered; - - private void tryOutputSubmit() { - var syncStatus = this.syncStatus(); - var currentBlockNum = Boolean.TRUE.equals(config.allowNonFinalized()) - ? syncStatus.safeL2().number() - : syncStatus.finalizedL2().number(); - var output = this.fetchOutputInfo(currentBlockNum); - if (output != null) { - this.sendOutputTx(currentBlockNum, output, syncStatus); - } - } - - private OutputRootResult fetchOutputInfo(BigInteger currentBlockNum) { - BigInteger nextCheckPointBlockNum = this.nextCheckPointBlock(); - if (currentBlockNum.compareTo(nextCheckPointBlockNum) < 0) { - return null; - } - return this.outputAtBlock(nextCheckPointBlockNum); - } - - private Object sendOutputTx( - final BigInteger curBlock, final OutputRootResult output, final SyncStatusResult status) { - this.waitL1Head(status.headL1().number().add(BigInteger.ONE)); - Function proposeL2OutputFn = null; - try { - proposeL2OutputFn = FunctionEncoder.makeFunction( - "proposeL2Output", - List.of("bytes32", "uint256", "bytes32", "uint256"), - List.of( - Numeric.hexStringToByteArray(output.outputRoot()), - curBlock, - status.currentL1().hash(), - status.currentL1().number()), - List.of()); - } catch (ReflectiveOperationException e) { - throw new OutputSubmitterExecution(e); - } - - String fnData = FunctionEncoder.encode(proposeL2OutputFn); - - // todo parameter - RawTransaction tx = RawTransaction.createTransaction( - this.config.l2ChainId(), - this.getNonce(), - BigInteger.ZERO, - this.config.l2OutputOracleAddr(), - BigInteger.ZERO, - fnData, - BigInteger.ZERO, - BigInteger.ZERO); - var receipt = Web3jUtil.executeContractReturnReceipt(l2Client, tx, this.config.l2ChainId(), this.l2From); - Optional txOption = receipt.getTransactionReceipt(); - if (txOption.isPresent() && txOption.get().isStatusOK()) { - LOGGER.info( - "proposer tx successfully published: tx_hash = {}, l1BlockNum = {}, l1BlockHash = {}", - txOption.get().getTransactionHash(), - status.currentL1().number(), - status.currentL1().hash()); - } else { - LOGGER.error( - "proposer tx successfully published but reverted: tx_hash = {}", - txOption.map(TransactionReceipt::getTransactionHash).orElse(null)); - } - return null; - } - - private BigInteger getNonce() { - if (nonce == null) { - nonce = Web3jUtil.getTxCount(this.l2Client, this.l2From.getAddress()); - } else { - nonce = nonce.add(BigInteger.ONE); - } - return nonce; - } - - private void waitL1Head(final BigInteger headNum) { - try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { - scope.fork(() -> { - BigInteger l1Head = BigInteger.ZERO; - do { - if (l1Head.compareTo(BigInteger.ZERO) == 0) { - Thread.sleep(this.config.pollInterval()); - } - var blockNumResp = l1Client.ethBlockNumber().sendAsync().get(); - if (blockNumResp != null) { - l1Head = blockNumResp.getBlockNumber(); - } - } while (l1Head.compareTo(headNum) <= 0); - return null; - }); - scope.join(); - } catch (InterruptedException e) { - throw new OutputSubmitterExecution(e); - } - } - - private BigInteger nextCheckPointBlock() { - // l2 oracle contract fetches next block number - Function nextBlockNumberFn = null; - try { - nextBlockNumberFn = - FunctionEncoder.makeFunction("nextBlockNumber", List.of(), List.of(), List.of("uint256")); - } catch (ReflectiveOperationException e) { - throw new OutputSubmitterExecution(e); - } - List resp = Web3jUtil.executeContract( - this.l2Client, this.l2From.getAddress(), this.config.l2OutputOracleAddr(), nextBlockNumberFn); - return resp.isEmpty() ? null : ((Uint256) resp.get(0)).getValue(); - } - - private OutputRootResult outputAtBlock(BigInteger blockNumber) { - try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { - var outputInfo = scope.fork(TracerTaskWrapper.wrap(() -> { - return new Request<>( - "optimism_outputAtBlock", - Collections.singletonList(blockNumber), - this.rollUpClient, - Web3Sha3.class) - .send() - .getResult(); - })); - scope.join(); - scope.throwIfFailed(); - return mapper.readValue(outputInfo.get(), OutputRootResult.class); - } catch (InterruptedException | ExecutionException | IOException e) { - throw new OutputSubmitterExecution(e); - } - } - - private SyncStatusResult syncStatus() { - try (var scope = new StructuredTaskScope.ShutdownOnFailure()) { - var outputInfo = scope.fork(TracerTaskWrapper.wrap(() -> { - return new Request<>("optimism_syncStatus", List.of(), this.rollUpClient, Web3Sha3.class) - .send() - .getResult(); - })); - scope.join(); - scope.throwIfFailed(); - return mapper.readValue(outputInfo.get(), SyncStatusResult.class); - } catch (InterruptedException | ExecutionException | IOException e) { - throw new OutputSubmitterExecution(e); - } - } - - /** - * The L2OutputSubmitter constructor. - * @param config The proposer config. - */ - public L2OutputSubmitter(Config config) { - this.config = config; - this.l1Client = Web3jProvider.createClient(config.l1RpcUrl()); - this.l2Client = Web3jProvider.createClient(config.l2RpcUrl()); - this.l2From = Credentials.create(config.l2Signer()); - var tuple = Web3jProvider.create(config.rollupRpc()); - this.rollUpClient = tuple.component2(); - this.mapper = new ObjectMapper(); - } - - @Override - protected void run() throws Exception { - try { - while (isRunning() && !this.isShutdownTriggered) { - this.tryOutputSubmit(); - Thread.sleep(config.pollInterval()); - } - } catch (InterruptedException e) { - throw new OutputSubmitterExecution(""); - } - } - - @Override - protected void shutDown() throws Exception { - super.shutDown(); - } - - @Override - protected void triggerShutdown() { - this.isShutdownTriggered = true; - } -} diff --git a/hildr-proposer/src/main/java/io/optimism/proposer/cli/Cli.java b/hildr-proposer/src/main/java/io/optimism/proposer/cli/Cli.java deleted file mode 100644 index 96173448..00000000 --- a/hildr-proposer/src/main/java/io/optimism/proposer/cli/Cli.java +++ /dev/null @@ -1,125 +0,0 @@ -package io.optimism.proposer.cli; - -import ch.qos.logback.classic.Level; -import io.optimism.cli.typeconverter.LogLevelConverter; -import io.optimism.proposer.L2OutputSubmitter; -import io.optimism.proposer.config.Config; -import io.optimism.utilities.telemetry.Logging; -import io.optimism.utilities.telemetry.TracerTaskWrapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import picocli.CommandLine; -import sun.misc.Signal; - -/** - * Proposer CLI handler. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class Cli implements Runnable { - - private static final Logger LOGGER = LoggerFactory.getLogger(Cli.class); - - @CommandLine.Option(names = "--enable-metrics", required = false, description = "Enable metrics server") - boolean enableMetrics; - - @CommandLine.Option(names = "--l1-rpc-url", required = true, description = "The L1 chain RPC URL") - String l1RpcUrl; - - @CommandLine.Option(names = "--l2-rpc-url", required = true, description = "The L2 engine RPC URL") - String l2RpcUrl; - - @CommandLine.Option(names = "--rollup-rpc-url", required = true, description = "The rollup node RPC URL") - String rollupRpcUrl; - - @CommandLine.Option(names = "--l2-chain-id", required = true, description = "The L2 chain ID") - Long l2ChainId; - - @CommandLine.Option(names = "--l2-signer", required = true, description = "The L2 chain private key") - String l2Signer; - - @CommandLine.Option(names = "--l2oo-address", description = "The L2 output oracle contract address") - String l2OutputOracleAddr; - - @CommandLine.Option(names = "--l2dgf-address", description = "The L2 dispute game factory contract address") - String dgfContractAddr; - - @CommandLine.Option( - names = "--poll-interval", - defaultValue = "300", - description = "How frequently to poll L2 for new blocks") - Long pollInterval; - - @CommandLine.Option( - names = "--network-timeout", - defaultValue = "300", - description = "How frequently to poll L2 for new blocks") - Long networkTimeout; - - @CommandLine.Option( - names = "--allow-non-finalized", - defaultValue = "false", - description = "Allow the proposer to submit proposals for L2 blocks derived from non-finalized L1 blocks") - boolean allowNonFinalized; - - @CommandLine.Option( - names = "--log-level", - defaultValue = "DEBUG", - converter = LogLevelConverter.class, - description = "Log level") - Level logLevel; - - /** - * The proposer CLI constructor. - */ - public Cli() {} - - @Override - public void run() { - var logger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); - if (logger instanceof ch.qos.logback.classic.Logger) { - var logbackLogger = (ch.qos.logback.classic.Logger) logger; - logbackLogger.setLevel(logLevel); - } - TracerTaskWrapper.setTracerSupplier(Logging.INSTANCE::getTracer); - - // listen close signal - Signal.handle(new Signal("INT"), sig -> System.exit(0)); - Signal.handle(new Signal("TERM"), sig -> System.exit(0)); - - var tracer = Logging.INSTANCE.getTracer("hildr-proposer-cli"); - var span = tracer.nextSpan().name("proposer-submitter").start(); - try (var unused = tracer.withSpan(span)) { - // if (this.enableMetrics) { - // // todo start metrics server - // } - // start l2 output submitter - var submitter = new L2OutputSubmitter(optionToConfig()); - submitter.startAsync().awaitTerminated(); - } catch (Exception e) { - LOGGER.error("hildr proposer: ", e); - throw new RuntimeException(e); - } finally { - if (this.enableMetrics) { - LOGGER.info("stop metrics"); - // todo stop metrics server - } - span.end(); - } - } - - private Config optionToConfig() { - return new Config( - this.l2ChainId, - this.l1RpcUrl, - this.l2RpcUrl, - this.rollupRpcUrl, - this.l2Signer, - this.l2OutputOracleAddr, - this.dgfContractAddr, - this.pollInterval, - this.networkTimeout, - this.allowNonFinalized); - } -} diff --git a/hildr-proposer/src/main/java/io/optimism/proposer/config/Config.java b/hildr-proposer/src/main/java/io/optimism/proposer/config/Config.java deleted file mode 100644 index c0422ec5..00000000 --- a/hildr-proposer/src/main/java/io/optimism/proposer/config/Config.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.optimism.proposer.config; - -/** - * The proposer config. - * - * @param l2ChainId The chain ID for L2. - * @param l1RpcUrl The HTTP URL for L1. - * @param l2RpcUrl The HTTP URL for L2. - * @param rollupRpc The HTTP URL for the rollup node. - * @param l2Signer The signer for L2. - * @param l2OutputOracleAddr The L2OutputOracle contract address. - * @param dgfContractAddr The DisputeGameFactory contract address. - * @param pollInterval The delay between querying L2 for more transaction and creating a new batch. - * @param networkTimeout network timeout. - * @param allowNonFinalized set to true to propose outputs for L2 blocks derived from non-finalized - * L1 data - * @author thinkAfCod - * @since 0.1.1 - */ -public record Config( - Long l2ChainId, - String l1RpcUrl, - String l2RpcUrl, - String rollupRpc, - String l2Signer, - String l2OutputOracleAddr, - String dgfContractAddr, - Long pollInterval, - Long networkTimeout, - Boolean allowNonFinalized) {} diff --git a/hildr-proposer/src/main/java/io/optimism/proposer/exception/OutputSubmitterExecution.java b/hildr-proposer/src/main/java/io/optimism/proposer/exception/OutputSubmitterExecution.java deleted file mode 100644 index dabdf41f..00000000 --- a/hildr-proposer/src/main/java/io/optimism/proposer/exception/OutputSubmitterExecution.java +++ /dev/null @@ -1,38 +0,0 @@ -package io.optimism.proposer.exception; - -/** - * output submitter execution exception. - * - * @author thinkAfCod - * @since 0.1.1 - */ -public class OutputSubmitterExecution extends RuntimeException { - - /** - * Instantiates a new output execution exception. - * - * @param message the message - */ - public OutputSubmitterExecution(String message) { - super(message); - } - - /** - * Instantiates a new output execution exception. - * - * @param message the message - * @param cause the cause - */ - public OutputSubmitterExecution(String message, Throwable cause) { - super(message, cause); - } - - /** - * Instantiates a new output execution exception. - * - * @param cause the cause - */ - public OutputSubmitterExecution(Throwable cause) { - super(cause); - } -} diff --git a/hildr-proposer/src/main/resources/logback.xml b/hildr-proposer/src/main/resources/logback.xml deleted file mode 100644 index 0e2c6a65..00000000 --- a/hildr-proposer/src/main/resources/logback.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} trace_id=%X{trace_id} span_id=%X{span_id} trace_flags=%X{trace_flags} %msg%n - - - - - logs/app.log - - app-%d{yyyy-MM-dd HH}.gz - 30 - 3GB - - - %d{HH:mm:ss.SSS} %-5level %logger{36} trace_id=%X{trace_id} span_id=%X{span_id} trace_flags=%X{trace_flags} %msg%n - - - - - - - - - - - diff --git a/settings.gradle b/settings.gradle index 8acae4f0..77b85e26 100644 --- a/settings.gradle +++ b/settings.gradle @@ -16,7 +16,5 @@ pluginManagement { rootProject.name = 'hildr' include('hildr-node') -include('hildr-batcher') include('hildr-utilities') -include ('hildr-proposer')