diff --git a/docker/.env.default b/docker/.env.default index da86ffe8..a99a90fc 100644 --- a/docker/.env.default +++ b/docker/.env.default @@ -1,4 +1,4 @@ -# L1 network option: can be either `optimism-goerli` or `base-goerli` +# L1 network option: can be either `optimism`, `optimism-goerli`, `optimism-sepolia` or `base-goerli` NETWORK=optimism # The HTTP RPC endpoint of an L1 node @@ -16,9 +16,28 @@ RPC_PORT=9545 # Execution client: can be either `op-geth` or `op-erigon` EXECUTION_CLIENT=op-geth +# The exeuction client Auth RPC port. +EXECUTION_CLIENT_AUTH_RPC_PORT=8551 + +# The execution client RPC port. +EXECUTION_CLIENT_RPC_PORT=8545 + +# The execution client WebSocket port. +EXECUTION_CLIENT_WS_PORT=8546 + # Sync mode: can be either `full` or `checkpoint` SYNC_MODE=full +# Only for `custom` or `devnet` network. +# Specify the path to the `rollup.json` file generated by `op-node`. +# For the devnet configuration, this file should be located in the `.devnet` folder within the Optimism directory. +# OP_ROLLUP_JSON_FILEPATH= + +# Only for `custom` or `devnet` network. +# Specify the path to the `genesis-l2.json` file generated by `op-node`. +# For the devnet configuration, this file should be located in the `.devnet` folder within the Optimism directory. +# OP_GENESIS_JSON_FILEPATH= + # If the OP-Challenger should be run as a service alongside Magi # (comment out the next line if you don't want to run this service) #RUN_OP_CHALLENGER=run-op-challenger diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index f873f279..467c0756 100755 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -29,6 +29,7 @@ services: volumes: - ./:/scripts - data:/data + - ${OP_ROLLUP_JSON_FILEPATH:-.}:/rollup.json <<: *logging op-geth: @@ -42,12 +43,13 @@ services: env_file: - .env ports: - - 8551:8551 - - 8545:8545 - - 8546:8546 + - ${EXECUTION_CLIENT_AUTH_RPC_PORT}:8551 + - ${EXECUTION_CLIENT_RPC_PORT}:8545 + - ${EXECUTION_CLIENT_WS_PORT}:8546 volumes: - ./:/scripts - data:/data + - ${OP_GENESIS_JSON_FILEPATH:-.}:/genesis-l2.json <<: *logging op-erigon: @@ -61,9 +63,9 @@ services: env_file: - .env ports: - - 8551:8551 - - 8545:8545 - - 8546:8546 + - ${EXECUTION_CLIENT_AUTH_RPC_PORT}:8551 + - ${EXECUTION_CLIENT_RPC_PORT}:8545 + - ${EXECUTION_CLIENT_WS_PORT}:8546 volumes: - ./:/scripts - data:/data diff --git a/docker/start-hildr-node.sh b/docker/start-hildr-node.sh index 3890fdbe..96cd239a 100755 --- a/docker/start-hildr-node.sh +++ b/docker/start-hildr-node.sh @@ -1,5 +1,15 @@ #!/bin/sh set -e +DEVNET="" + +if [ $NETWORK = "custom" ] || [ $NETWORK = "devnet" ] +then + NETWORK="./rollup.json" + if [ "$NETWORK" = "devnet" ] + then + DEVNET="--devnet" + fi +fi if [ $SYNC_MODE = "full" ] then @@ -10,6 +20,7 @@ then --l2-rpc-url http://${EXECUTION_CLIENT}:8545 \ --l2-engine-url http://${EXECUTION_CLIENT}:8551 \ --rpc-port $RPC_PORT \ + $DEVNET \ --sync-mode $SYNC_MODE elif [ $SYNC_MODE = "checkpoint"] then @@ -20,6 +31,7 @@ then --l2-rpc-url http://${EXECUTION_CLIENT}:8545 \ --l2-engine-url http://${EXECUTION_CLIENT}:8551 \ --rpc-port $RPC_PORT \ + $DEVNET \ --sync-mode $SYNC_MODE \ --checkpoint-sync-url $CHECKPOINT_SYNC_URL \ --checkpoint-hash $CHECKPOINT_HASH diff --git a/docker/start-op-erigon.sh b/docker/start-op-erigon.sh index e0ed37c2..11d4d742 100755 --- a/docker/start-op-erigon.sh +++ b/docker/start-op-erigon.sh @@ -20,7 +20,7 @@ fi echo $JWT_SECRET > jwtsecret.txt -erigon \ +exec erigon \ --datadir=$DATADIR \ --private.api.addr=localhost:9090 \ --http.addr=0.0.0.0 \ diff --git a/docker/start-op-geth.sh b/docker/start-op-geth.sh index e0285c35..bce09b58 100755 --- a/docker/start-op-geth.sh +++ b/docker/start-op-geth.sh @@ -1,6 +1,9 @@ #!/bin/sh set -e +apk add zstd +apk add jq + DATADIR=/data/geth if [ $NETWORK = "optimism" ] @@ -9,8 +12,8 @@ then if [ ! -d $DATADIR ] then mkdir $DATADIR - wget -c "https://storage.googleapis.com/oplabs-mainnet-data/mainnet-bedrock.tar" -P $DATADIR - tar -xvf $DATADIR/mainnet-bedrock.tar -C $DATADIR + wget "https://datadirs.optimism.io/mainnet-bedrock.tar.zst" -P $DATADIR + zstd -cd $DATADIR/mainnet-bedrock.tar.zst | tar xvf - -C $DATADIR fi elif [ $NETWORK = "base" ] then @@ -19,7 +22,7 @@ then then mkdir $DATADIR wget "https://raw.githubusercontent.com/base-org/node/main/mainnet/genesis-l2.json" -O ./genesis-l2.json - exec geth init --datadir=$DATADIR ./genesis-l2.json + geth init --datadir=$DATADIR ./genesis-l2.json fi elif [ $NETWORK = "optimism-goerli" ] then @@ -27,8 +30,16 @@ then if [ ! -d $DATADIR ] then mkdir $DATADIR - wget "https://storage.googleapis.com/oplabs-goerli-data/goerli-bedrock.tar" -P $DATADIR - tar -xvf $DATADIR/goerli-bedrock.tar -C $DATADIR + wget "https://datadirs.optimism.io/goerli-bedrock.tar.zst" -P $DATADIR + zstd -cd $DATADIR/goerli-bedrock.tar.zst | tar xvf - -C $DATADIR + fi +elif [ "$NETWORK" = "optimism-sepolia" ] +then + CHAIN_ID=11155420 + if [ ! -d "$DATADIR" ] + then + wget "https://storage.googleapis.com/oplabs-network-data/Sepolia/genesis.json" -O ./genesis-l2.json + geth init --datadir=$DATADIR ./genesis-l2.json fi elif [ $NETWORK = "base-goerli" ] then @@ -36,13 +47,23 @@ then if [ ! -d $DATADIR ] then wget "https://raw.githubusercontent.com/base-org/node/main/goerli/genesis-l2.json" -O ./genesis-l2.json - exec geth init --datadir=$DATADIR ./genesis-l2.json + geth init --datadir=$DATADIR ./genesis-l2.json + fi +elif [ $NETWORK = "custom" ] || [ $NETWORK = "devnet" ] +then + CHAIN_ID=$(jq '.config.chainId' ./genesis-l2.json) + + if [ ! -d $DATADIR ] + then + mkdir $DATADIR + geth init --datadir=$DATADIR ./genesis-l2.json fi else echo "Network not recognized. Available options are optimism-goerli and base-goerli" exit 1 fi + echo $JWT_SECRET > jwtsecret.txt echo "chain id" @@ -65,3 +86,5 @@ exec geth \ --authrpc.port=8551 \ --authrpc.jwtsecret=/jwtsecret.txt \ --rollup.disabletxpoolgossip=true \ + --snapshot=false + $@ diff --git a/hildr-node/src/main/java/io/optimism/cli/Cli.java b/hildr-node/src/main/java/io/optimism/cli/Cli.java index 9ed4539e..002a78a6 100644 --- a/hildr-node/src/main/java/io/optimism/cli/Cli.java +++ b/hildr-node/src/main/java/io/optimism/cli/Cli.java @@ -24,8 +24,12 @@ import io.optimism.telemetry.InnerMetrics; import io.optimism.utilities.telemetry.Logging; import io.optimism.utilities.telemetry.TracerTaskWrapper; +import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import picocli.CommandLine.Command; @@ -70,6 +74,11 @@ public class Cli implements Runnable { description = "Engine API JWT Secret. This is used to authenticate with the engine API") String jwtSecret; + @Option( + names = "--jwt-file", + description = "Path to a JWT secret to use for authenticated RPC endpoints") + String jwtFile; + @Option( names = {"--verbose", "-v"}, description = "") @@ -91,6 +100,9 @@ public class Cli implements Runnable { description = "A trusted L2 RPC URL to use for fast/checkpoint syncing") String checkpointSyncUrl; + @Option(names = "--devnet", description = "Dev net flag") + private Boolean devnet; + /** the Cli constructor. */ public Cli() {} @@ -133,6 +145,8 @@ private Config toConfig() { switch (network) { case "optimism" -> Config.ChainConfig.optimism(); case "optimism-goerli" -> Config.ChainConfig.optimismGoerli(); + case "optimism-sepolia" -> Config.ChainConfig.optimismSepolia(); + case "base" -> Config.ChainConfig.base(); case "base-goerli" -> Config.ChainConfig.baseGoerli(); default -> { if (network.endsWith(".json")) { @@ -147,13 +161,36 @@ private Config toConfig() { return Config.create(Files.exists(configPath) ? configPath : null, cliConfig, chain); } + private String getJwtSecret() { + if (StringUtils.isNotEmpty(Cli.this.jwtSecret)) { + return Cli.this.jwtSecret; + } + return Cli.this.getJwtFromFile(); + } + + private String getJwtFromFile() { + final Path jwtFilePath = + StringUtils.isNotEmpty(Cli.this.jwtFile) + ? Paths.get(Cli.this.jwtFile) + : Paths.get(System.getProperty("user.dir"), "jwt.hex"); + if (!Files.exists(jwtFilePath)) { + throw new RuntimeException("Failed to read JWT secret from file: " + jwtFilePath); + } + try { + return Files.readString(jwtFilePath, StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException("Failed to read JWT secret from file: " + jwtFilePath, e); + } + } + private Config.CliConfig from(Cli cli) { return new Config.CliConfig( cli.l1RpcUrl, cli.l2RpcUrl, cli.l2EngineUrl, - cli.jwtSecret, + Cli.this.getJwtSecret(), cli.checkpointSyncUrl, - cli.rpcPort); + cli.rpcPort, + cli.devnet); } } diff --git a/hildr-node/src/main/java/io/optimism/config/Config.java b/hildr-node/src/main/java/io/optimism/config/Config.java index 1b914a1a..9a356598 100644 --- a/hildr-node/src/main/java/io/optimism/config/Config.java +++ b/hildr-node/src/main/java/io/optimism/config/Config.java @@ -139,6 +139,7 @@ public static Config create(Path configPath, CliConfig cliConfig, ChainConfig ch * @param jwtSecret L2 engine API jwt secret. * @param checkpointSyncUrl The checkpoint sync url. * @param rpcPort The rpc port. + * @param devnet The devnet flag. */ public record CliConfig( String l1RpcUrl, @@ -146,7 +147,8 @@ public record CliConfig( String l2EngineUrl, String jwtSecret, String checkpointSyncUrl, - Integer rpcPort) { + Integer rpcPort, + Boolean devnet) { /** * To configMap. @@ -254,6 +256,43 @@ public static ChainConfig optimism() { "0x4200000000000000000000000000000000000016"); } + /** + * Optimism sepolia ChainConfig. + * + * @return the chain config + */ + public static ChainConfig optimismSepolia() { + return new ChainConfig( + "base-goerli", + BigInteger.valueOf(11155111L), + BigInteger.valueOf(11155420L), + new Epoch( + BigInteger.valueOf(4071408L), + "0x48f520cf4ddaf34c8336e6e490632ea3cf1e5e93b0b2bc6e917557e31845371b", + BigInteger.valueOf(1691802540L)), + new BlockInfo( + "0x102de6ffb001480cc9b8b548fd05c34cd4f46ae4aa91759393db90ea0409887d", + BigInteger.valueOf(0L), + Numeric.toHexString(new byte[32]), + BigInteger.valueOf(1691802540L)), + new SystemConfig( + "0x8F23BB38F531600e5d8FDDaAEC41F13FaB46E98c", + BigInteger.valueOf(30_000_000L), + BigInteger.valueOf(188), + BigInteger.valueOf(684000), + "0x0000000000000000000000000000000000000000"), + "0xff00000000000000000000000000000011155420", + "0x16fc5058f25648194471939df75cf27a2fdc48bc", + "0x034edd2a225f7f429a63e0f1d2084b9e0a93b538", + BigInteger.valueOf(100_000_000L), + BigInteger.valueOf(300L), + BigInteger.valueOf(3600L), + BigInteger.valueOf(600L), + BigInteger.ZERO, + BigInteger.valueOf(2L), + "0x4200000000000000000000000000000000000016"); + } + /** * Base mainnet chain config. * @@ -286,7 +325,7 @@ public static ChainConfig base() { BigInteger.valueOf(300L), BigInteger.valueOf(3600L), BigInteger.valueOf(600L), - BigInteger.valueOf(Long.MAX_VALUE), + BigInteger.ZERO, BigInteger.valueOf(2L), "0x4200000000000000000000000000000000000016"); } @@ -360,7 +399,7 @@ public static ChainConfig baseGoerli() { BigInteger.valueOf(100L), BigInteger.valueOf(3600L), BigInteger.valueOf(600L), - BigInteger.valueOf(Long.MAX_VALUE), + BigInteger.valueOf(1683219600L), BigInteger.valueOf(2L), "0x4200000000000000000000000000000000000016"); } @@ -416,7 +455,7 @@ public static ChainConfig fromExternal(ExternalChainConfig external) { external.maxSequencerDrift, external.regolithTime, external.blockTime, - Numeric.toHexString(new byte[32])); + "0x4200000000000000000000000000000000000016"); } /** diff --git a/hildr-node/src/main/java/io/optimism/derive/State.java b/hildr-node/src/main/java/io/optimism/derive/State.java index 0c49d426..5e5c5f41 100644 --- a/hildr-node/src/main/java/io/optimism/derive/State.java +++ b/hildr-node/src/main/java/io/optimism/derive/State.java @@ -134,16 +134,6 @@ public Epoch epoch(BigInteger number) { l1Info.blockInfo().number(), l1Info.blockInfo().hash(), l1Info.blockInfo().timestamp()); } - /** - * Is full boolean. - * - * @return the boolean - */ - public boolean isFull() { - return this.currentEpochNum.compareTo(this.safeEpoch.number().add(BigInteger.valueOf(1000L))) - > 0; - } - /** * Update l 1 info. * diff --git a/hildr-node/src/main/java/io/optimism/driver/Driver.java b/hildr-node/src/main/java/io/optimism/driver/Driver.java index 9872e914..001bd195 100644 --- a/hildr-node/src/main/java/io/optimism/driver/Driver.java +++ b/hildr-node/src/main/java/io/optimism/driver/Driver.java @@ -332,8 +332,14 @@ private void advanceSafeHead() throws ExecutionException, InterruptedException { Driver.this.engineDriver.getSafeHead().number(), Driver.this.engineDriver.getSafeHead().hash()); - BlockInfo newSafeHead = Driver.this.engineDriver.getSafeHead(); - Epoch newSafeEpoch = Driver.this.engineDriver.getSafeEpoch(); + final BlockInfo newSafeHead = Driver.this.engineDriver.getSafeHead(); + final Epoch newSafeEpoch = Driver.this.engineDriver.getSafeEpoch(); + + Driver.this.state.getAndUpdate( + state -> { + state.updateSafeHead(newSafeHead, newSafeEpoch); + return state; + }); UnfinalizedBlock newUnfinalizedBlock = new UnfinalizedBlock(newSafeHead, newSafeEpoch, l1InclusionBlock, seqNumber); @@ -387,10 +393,6 @@ private void updateStateHead() { @SuppressWarnings("preview") private void handleNextBlockUpdate() { - boolean isStateFull = this.state.get().isFull(); - if (isStateFull) { - return; - } BlockUpdate next = this.chainWatcher.getBlockUpdateQueue().poll(); if (next == null) { return; diff --git a/hildr-node/src/test/java/io/optimism/HildrTest.java b/hildr-node/src/test/java/io/optimism/HildrTest.java index e9fb9d6a..8340780e 100644 --- a/hildr-node/src/test/java/io/optimism/HildrTest.java +++ b/hildr-node/src/test/java/io/optimism/HildrTest.java @@ -39,7 +39,7 @@ class HildrTest { */ @Test void appHasGreeting() throws JsonProcessingException { - CliConfig cliConfig = new CliConfig("test", "test", "test", "test", null, null); + CliConfig cliConfig = new CliConfig("test", "test", "test", "test", null, null, false); TomlMapper mapper = new TomlMapper(); String cliConfigStr = mapper.writerFor(CliConfig.class).writeValueAsString(cliConfig); diff --git a/hildr-node/src/test/java/io/optimism/TestConstants.java b/hildr-node/src/test/java/io/optimism/TestConstants.java index 139c6cbd..308a962e 100644 --- a/hildr-node/src/test/java/io/optimism/TestConstants.java +++ b/hildr-node/src/test/java/io/optimism/TestConstants.java @@ -55,7 +55,7 @@ public static Config createConfig() { var l1RpcUrl = l1RpcUrlFormat.formatted(envs.get(ETH_API_ENV)); var l2RpcUrl = l2RpcUrlFormat.formatted(envs.get(OPT_API_ENV)); Config.CliConfig cliConfig = - new Config.CliConfig(l1RpcUrl, l2RpcUrl, null, "testjwt", null, null); + new Config.CliConfig(l1RpcUrl, l2RpcUrl, null, "testjwt", null, null, false); return Config.create(null, cliConfig, Config.ChainConfig.optimismGoerli()); } } diff --git a/hildr-node/src/test/java/io/optimism/config/ConfigTest.java b/hildr-node/src/test/java/io/optimism/config/ConfigTest.java index cdc6adf3..441268cb 100644 --- a/hildr-node/src/test/java/io/optimism/config/ConfigTest.java +++ b/hildr-node/src/test/java/io/optimism/config/ConfigTest.java @@ -40,7 +40,7 @@ class ConfigTest { /** Create. */ @Test void create() { - CliConfig cliConfig = new CliConfig(null, null, null, "testjwt", null, null); + CliConfig cliConfig = new CliConfig(null, null, null, "testjwt", null, null, false); Config config = Config.create( Paths.get("src", "test", "resources", "test.toml"), @@ -98,7 +98,7 @@ static class ChainConfigTest { @Test void baseGoerli() { ChainConfig chainConfig = ChainConfig.baseGoerli(); - assertEquals(chainConfig.regolithTime(), BigInteger.valueOf(Long.MAX_VALUE)); + assertEquals(chainConfig.regolithTime(), BigInteger.valueOf(1683219600L)); } /** Base goerli. */ diff --git a/hildr-node/src/test/java/io/optimism/driver/DriverTest.java b/hildr-node/src/test/java/io/optimism/driver/DriverTest.java index bbc6c594..ce2b6070 100644 --- a/hildr-node/src/test/java/io/optimism/driver/DriverTest.java +++ b/hildr-node/src/test/java/io/optimism/driver/DriverTest.java @@ -48,7 +48,8 @@ void testNewDriverFromFinalizedHead() null, "d195a64e08587a3f1560686448867220c2727550ce3e0c95c7200d0ade0f9167", l2rpc, - null); + null, + false); Config config = Config.create(null, cliConfig, ChainConfig.optimismGoerli()); Web3j provider = Web3j.build(new HttpService(config.l2RpcUrl()));