From b16635c5fbf731a24a211554ceec7124155d7160 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Mon, 23 Oct 2023 17:27:55 +0100 Subject: [PATCH 01/13] Initial optimism layout --- Cargo.lock | 115 ++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + optimism/Cargo.toml | 29 +++++++++++ optimism/src/lib.rs | 0 optimism/src/main.rs | 6 +++ 5 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 optimism/Cargo.toml create mode 100644 optimism/src/lib.rs create mode 100644 optimism/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index c8b7f9249a..8028b4f6d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,6 +46,54 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "anstream" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +dependencies = [ + "anstyle", + "windows-sys", +] + [[package]] name = "ark-algebra-test-templates" version = "0.3.0" @@ -417,7 +465,7 @@ dependencies = [ "atty", "bitflags 1.3.2", "clap_derive", - "clap_lex", + "clap_lex 0.2.4", "indexmap", "once_cell", "strsim 0.10.0", @@ -425,6 +473,27 @@ dependencies = [ "textwrap 0.16.0", ] +[[package]] +name = "clap" +version = "4.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d04704f56c2cde07f43e8e2c154b43f216dc5c92fc98ada720177362f953b956" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e231faeaca65ebd1ea3c737966bf858971cd38c3849107aa3ea7de90a804e45" +dependencies = [ + "anstream", + "anstyle", + "clap_lex 0.5.1", + "strsim 0.10.0", +] + [[package]] name = "clap_derive" version = "3.2.25" @@ -447,6 +516,18 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "clap_lex" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "colored" version = "2.0.4" @@ -727,6 +808,12 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +[[package]] +name = "elf" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6e7d85896690fe195447717af8eceae0593ac2196fd42fe88c184e904406ce" + [[package]] name = "entities" version = "1.0.1" @@ -1159,6 +1246,26 @@ dependencies = [ "tinytemplate", ] +[[package]] +name = "kimchi_optimism" +version = "0.1.0" +dependencies = [ + "ark-ff", + "ark-poly", + "clap 4.4.6", + "elf", + "groupmap", + "hex", + "kimchi", + "mina-curves", + "mina-poseidon", + "poly-commitment", + "rmp-serde", + "serde", + "serde_json", + "serde_with", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -2636,6 +2743,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "vec_map" version = "0.8.2" diff --git a/Cargo.toml b/Cargo.toml index c50da37068..851713bf6b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "groupmap", "hasher", "kimchi", + "optimism", "poseidon", "poseidon/export_test_vectors", "poly-commitment", diff --git a/optimism/Cargo.toml b/optimism/Cargo.toml new file mode 100644 index 0000000000..9b45ab1d29 --- /dev/null +++ b/optimism/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "kimchi_optimism" +version = "0.1.0" +description = "MIPS demo" +repository = "https://github.com/o1-labs/proof-systems" +homepage = "https://o1-labs.github.io/proof-systems/" +documentation = "https://o1-labs.github.io/proof-systems/rustdoc/" +readme = "README.md" +edition = "2021" +license = "Apache-2.0" + +[lib] +path = "src/lib.rs" + +[dependencies] +kimchi = { path = "../kimchi", version = "0.1.0" } +poly-commitment = { path = "../poly-commitment", version = "0.1.0" } +groupmap = { path = "../groupmap", version = "0.1.0" } +mina-curves = { path = "../curves", version = "0.1.0" } +mina-poseidon = { path = "../poseidon", version = "0.1.0" } +elf = "0.7.2" +rmp-serde = "1.1.1" +serde_json = "1.0.91" +serde = "1.0.130" +serde_with = "1.10.0" +ark-poly = { version = "0.3.0", features = [ "parallel" ] } +ark-ff = { version = "0.3.0", features = [ "parallel" ] } +clap = "4.4.6" +hex = "0.4.3" diff --git a/optimism/src/lib.rs b/optimism/src/lib.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/optimism/src/main.rs b/optimism/src/main.rs new file mode 100644 index 0000000000..9301ced20f --- /dev/null +++ b/optimism/src/main.rs @@ -0,0 +1,6 @@ +use std:: process::ExitCode; + +pub fn main() -> ExitCode { + // TODO: Logic + ExitCode::FAILURE +} From eac8542b0bf7da2235bab978618f15df2433fa9a Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Mon, 23 Oct 2023 17:35:43 +0100 Subject: [PATCH 02/13] Checkout optimism v1.1.6 --- .gitmodules | 3 +++ optimism/ethereum-optimism | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 optimism/ethereum-optimism diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..5b1dec4f59 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "optimism/ethereum-optimism"] + path = optimism/ethereum-optimism + url = https://github.com/ethereum-optimism/optimism.git diff --git a/optimism/ethereum-optimism b/optimism/ethereum-optimism new file mode 160000 index 0000000000..c83cd947d4 --- /dev/null +++ b/optimism/ethereum-optimism @@ -0,0 +1 @@ +Subproject commit c83cd947d419aa2c213583a32872bc350a69e566 From e55460bbc025a73addd1f199d56e81f85ae9ad7a Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Mon, 23 Oct 2023 18:02:56 +0100 Subject: [PATCH 03/13] Check-in runner --- optimism/.gitignore | 1 + optimism/run-code.sh | 63 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 optimism/.gitignore create mode 100755 optimism/run-code.sh diff --git a/optimism/.gitignore b/optimism/.gitignore new file mode 100644 index 0000000000..53df36bb78 --- /dev/null +++ b/optimism/.gitignore @@ -0,0 +1 @@ +rpcs.sh diff --git a/optimism/run-code.sh b/optimism/run-code.sh new file mode 100755 index 0000000000..1452f2933f --- /dev/null +++ b/optimism/run-code.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +set -euo pipefail + +make -C ./ethereum-optimism/op-program op-program + +source rpcs.sh + +# L2 output oracle on Goerli +# L2_OUTPUT_ORACLE=0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0 +# L2 output oracle on Sepolia +L2_OUTPUT_ORACLE=0x90E9c4f8a994a250F6aEfd61CAFb4F2e895D458F + +L2_FINALIZED_NUMBER=$(cast block finalized --rpc-url "${L2RPC}" -f number) +echo "Finalize number: ${L2_FINALIZED_NUMBER}" +L2_FINALIZED_HASH=$(cast block "${L2_FINALIZED_NUMBER}" --rpc-url "${L2RPC}" -f hash) + +L1_FINALIZED_NUMBER=$(cast block finalized --rpc-url "${L1RPC}" -f number) +L1_FINALIZED_HASH=$(cast block "${L1_FINALIZED_NUMBER}" --rpc-url "${L1RPC}" -f hash) + +OUTPUT_INDEX=$(cast call --rpc-url "${L1RPC}" "${L2_OUTPUT_ORACLE}" 'getL2OutputIndexAfter(uint256) returns(uint256)' "${L2_FINALIZED_NUMBER}") +OUTPUT_INDEX=$((OUTPUT_INDEX-1)) + +OUTPUT=$(cast call --rpc-url "${L1RPC}" "${L2_OUTPUT_ORACLE}" 'getL2Output(uint256) returns(bytes32,uint128,uint128)' "${OUTPUT_INDEX}") +OUTPUT_ROOT=$(echo ${OUTPUT} | cut -d' ' -f 1) +OUTPUT_TIMESTAMP=$(echo ${OUTPUT} | cut -d' ' -f 2) +OUTPUT_L2BLOCK_NUMBER=$(echo ${OUTPUT} | cut -d' ' -f 3) + +L1_HEAD=$L1_FINALIZED_HASH +L2_CLAIM=$OUTPUT_ROOT +L2_BLOCK_NUMBER=$OUTPUT_L2BLOCK_NUMBER + +STARTING_L2BLOCK_NUMBER=$((L2_BLOCK_NUMBER-100)) +STARTING_OUTPUT_INDEX=$(cast call --rpc-url "${L1RPC}" "${L2_OUTPUT_ORACLE}" 'getL2OutputIndexAfter(uint256) returns(uint256)' "${STARTING_L2BLOCK_NUMBER}") +STARTING_OUTPUT=$(cast call --rpc-url "${L1RPC}" "${L2_OUTPUT_ORACLE}" 'getL2Output(uint256) returns(bytes32,uint128,uint128)' "${STARTING_OUTPUT_INDEX}") +STARTING_OUTPUT_ROOT=$(echo ${OUTPUT} | cut -d' ' -f 1) +L2_HEAD_NUMBER=$(echo ${OUTPUT} | cut -d' ' -f 3) +L2_HEAD=$(cast block "${L2_HEAD_NUMBER}" --rpc-url "${L2RPC}" -f hash) + +TODAY=$(date +"%Y-%m-%d-%H-%M-%S") +FILENAME=${TODAY}-op-program-data-log.sh +OP_PROGRAM_DATA_DIR=$(pwd)/op-program-db-sepolia-${TODAY} + +echo "L1_HEAD=${L1_HEAD}" >> ${FILENAME} +echo "L2_HEAD=${L2_HEAD}" >> ${FILENAME} +echo "L2_BLOCK_NUMBER=${L2_BLOCK_NUMBER}" >> ${FILENAME} +echo "STARTING_OUTPUT_ROOT=${STARTING_OUTPUT_ROOT}" >> ${FILENAME} +echo "L2_CLAIM=${L2_CLAIM}" >> ${FILENAME} +echo "OP_PROGRAM_DATA_DIR=${OP_PROGRAM_DATA_DIR}" >> ${FILENAME} +echo "L1RPC=${L1RPC}" >> ${FILENAME} +echo "L2RPC=${L2RPC}" >> ${FILENAME} + +set -x +./ethereum-optimism/op-program/bin/op-program \ + --log.level DEBUG \ + --l1 $L1RPC \ + --l2 $L2RPC \ + --network sepolia \ + --datadir ${OP_PROGRAM_DATA_DIR} \ + --l1.head $L1_HEAD \ + --l2.head $L2_HEAD \ + --l2.outputroot $STARTING_OUTPUT_ROOT \ + --l2.claim $L2_CLAIM \ + --l2.blocknumber $L2_BLOCK_NUMBER From 4fc60e939ed2ca457ff37fbc64c9b0b0c048d085 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Mon, 23 Oct 2023 18:07:27 +0100 Subject: [PATCH 04/13] Split out op-program runner --- optimism/run-code.sh | 47 ++++++++++++++------------------------ optimism/run-op-program.sh | 17 ++++++++++++++ 2 files changed, 34 insertions(+), 30 deletions(-) create mode 100755 optimism/run-op-program.sh diff --git a/optimism/run-code.sh b/optimism/run-code.sh index 1452f2933f..43cd300fe2 100755 --- a/optimism/run-code.sh +++ b/optimism/run-code.sh @@ -1,8 +1,6 @@ #!/usr/bin/env bash set -euo pipefail -make -C ./ethereum-optimism/op-program op-program - source rpcs.sh # L2 output oracle on Goerli @@ -25,39 +23,28 @@ OUTPUT_ROOT=$(echo ${OUTPUT} | cut -d' ' -f 1) OUTPUT_TIMESTAMP=$(echo ${OUTPUT} | cut -d' ' -f 2) OUTPUT_L2BLOCK_NUMBER=$(echo ${OUTPUT} | cut -d' ' -f 3) -L1_HEAD=$L1_FINALIZED_HASH -L2_CLAIM=$OUTPUT_ROOT -L2_BLOCK_NUMBER=$OUTPUT_L2BLOCK_NUMBER +export L1_HEAD=$L1_FINALIZED_HASH +export L2_CLAIM=$OUTPUT_ROOT +export L2_BLOCK_NUMBER=$OUTPUT_L2BLOCK_NUMBER STARTING_L2BLOCK_NUMBER=$((L2_BLOCK_NUMBER-100)) STARTING_OUTPUT_INDEX=$(cast call --rpc-url "${L1RPC}" "${L2_OUTPUT_ORACLE}" 'getL2OutputIndexAfter(uint256) returns(uint256)' "${STARTING_L2BLOCK_NUMBER}") STARTING_OUTPUT=$(cast call --rpc-url "${L1RPC}" "${L2_OUTPUT_ORACLE}" 'getL2Output(uint256) returns(bytes32,uint128,uint128)' "${STARTING_OUTPUT_INDEX}") -STARTING_OUTPUT_ROOT=$(echo ${OUTPUT} | cut -d' ' -f 1) +export STARTING_OUTPUT_ROOT=$(echo ${OUTPUT} | cut -d' ' -f 1) L2_HEAD_NUMBER=$(echo ${OUTPUT} | cut -d' ' -f 3) -L2_HEAD=$(cast block "${L2_HEAD_NUMBER}" --rpc-url "${L2RPC}" -f hash) +export L2_HEAD=$(cast block "${L2_HEAD_NUMBER}" --rpc-url "${L2RPC}" -f hash) TODAY=$(date +"%Y-%m-%d-%H-%M-%S") FILENAME=${TODAY}-op-program-data-log.sh -OP_PROGRAM_DATA_DIR=$(pwd)/op-program-db-sepolia-${TODAY} - -echo "L1_HEAD=${L1_HEAD}" >> ${FILENAME} -echo "L2_HEAD=${L2_HEAD}" >> ${FILENAME} -echo "L2_BLOCK_NUMBER=${L2_BLOCK_NUMBER}" >> ${FILENAME} -echo "STARTING_OUTPUT_ROOT=${STARTING_OUTPUT_ROOT}" >> ${FILENAME} -echo "L2_CLAIM=${L2_CLAIM}" >> ${FILENAME} -echo "OP_PROGRAM_DATA_DIR=${OP_PROGRAM_DATA_DIR}" >> ${FILENAME} -echo "L1RPC=${L1RPC}" >> ${FILENAME} -echo "L2RPC=${L2RPC}" >> ${FILENAME} - -set -x -./ethereum-optimism/op-program/bin/op-program \ - --log.level DEBUG \ - --l1 $L1RPC \ - --l2 $L2RPC \ - --network sepolia \ - --datadir ${OP_PROGRAM_DATA_DIR} \ - --l1.head $L1_HEAD \ - --l2.head $L2_HEAD \ - --l2.outputroot $STARTING_OUTPUT_ROOT \ - --l2.claim $L2_CLAIM \ - --l2.blocknumber $L2_BLOCK_NUMBER +export OP_PROGRAM_DATA_DIR=$(pwd)/op-program-db-sepolia-${TODAY} + +echo "export L1_HEAD=${L1_HEAD}" >> ${FILENAME} +echo "export L2_HEAD=${L2_HEAD}" >> ${FILENAME} +echo "export L2_BLOCK_NUMBER=${L2_BLOCK_NUMBER}" >> ${FILENAME} +echo "export STARTING_OUTPUT_ROOT=${STARTING_OUTPUT_ROOT}" >> ${FILENAME} +echo "export L2_CLAIM=${L2_CLAIM}" >> ${FILENAME} +echo "export OP_PROGRAM_DATA_DIR=${OP_PROGRAM_DATA_DIR}" >> ${FILENAME} +echo "export L1RPC=${L1RPC}" >> ${FILENAME} +echo "export L2RPC=${L2RPC}" >> ${FILENAME} + +./run-op-program.sh diff --git a/optimism/run-op-program.sh b/optimism/run-op-program.sh new file mode 100755 index 0000000000..f7936fee6e --- /dev/null +++ b/optimism/run-op-program.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -euo pipefail + +make -C ./ethereum-optimism/op-program op-program + +set -x +./ethereum-optimism/op-program/bin/op-program \ + --log.level DEBUG \ + --l1 $L1RPC \ + --l2 $L2RPC \ + --network sepolia \ + --datadir ${OP_PROGRAM_DATA_DIR} \ + --l1.head $L1_HEAD \ + --l2.head $L2_HEAD \ + --l2.outputroot $STARTING_OUTPUT_ROOT \ + --l2.claim $L2_CLAIM \ + --l2.blocknumber $L2_BLOCK_NUMBER From 0a715b74ff609e14a980aca2bf4e2bb5f9865dfd Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Mon, 23 Oct 2023 18:16:23 +0100 Subject: [PATCH 05/13] Separate out runner --- optimism/generate-config.sh | 50 +++++++++++++++++++++++++++++++++++++ optimism/run-code.sh | 44 ++------------------------------ 2 files changed, 52 insertions(+), 42 deletions(-) create mode 100755 optimism/generate-config.sh diff --git a/optimism/generate-config.sh b/optimism/generate-config.sh new file mode 100755 index 0000000000..e71f8a90ed --- /dev/null +++ b/optimism/generate-config.sh @@ -0,0 +1,50 @@ +#!/bin/bash +set -euo pipefail + +source rpcs.sh + +# L2 output oracle on Goerli +# L2_OUTPUT_ORACLE=0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0 +# L2 output oracle on Sepolia +L2_OUTPUT_ORACLE=0x90E9c4f8a994a250F6aEfd61CAFb4F2e895D458F + +L2_FINALIZED_NUMBER=$(cast block finalized --rpc-url "${L2RPC}" -f number) +echo "Finalize number: ${L2_FINALIZED_NUMBER}" 1>&2 +L2_FINALIZED_HASH=$(cast block "${L2_FINALIZED_NUMBER}" --rpc-url "${L2RPC}" -f hash) + +L1_FINALIZED_NUMBER=$(cast block finalized --rpc-url "${L1RPC}" -f number) +L1_FINALIZED_HASH=$(cast block "${L1_FINALIZED_NUMBER}" --rpc-url "${L1RPC}" -f hash) + +OUTPUT_INDEX=$(cast call --rpc-url "${L1RPC}" "${L2_OUTPUT_ORACLE}" 'getL2OutputIndexAfter(uint256) returns(uint256)' "${L2_FINALIZED_NUMBER}") +OUTPUT_INDEX=$((OUTPUT_INDEX-1)) + +OUTPUT=$(cast call --rpc-url "${L1RPC}" "${L2_OUTPUT_ORACLE}" 'getL2Output(uint256) returns(bytes32,uint128,uint128)' "${OUTPUT_INDEX}") +OUTPUT_ROOT=$(echo ${OUTPUT} | cut -d' ' -f 1) +OUTPUT_TIMESTAMP=$(echo ${OUTPUT} | cut -d' ' -f 2) +OUTPUT_L2BLOCK_NUMBER=$(echo ${OUTPUT} | cut -d' ' -f 3) + +L1_HEAD=$L1_FINALIZED_HASH +L2_CLAIM=$OUTPUT_ROOT +L2_BLOCK_NUMBER=$OUTPUT_L2BLOCK_NUMBER + +STARTING_L2BLOCK_NUMBER=$((L2_BLOCK_NUMBER-100)) +STARTING_OUTPUT_INDEX=$(cast call --rpc-url "${L1RPC}" "${L2_OUTPUT_ORACLE}" 'getL2OutputIndexAfter(uint256) returns(uint256)' "${STARTING_L2BLOCK_NUMBER}") +STARTING_OUTPUT=$(cast call --rpc-url "${L1RPC}" "${L2_OUTPUT_ORACLE}" 'getL2Output(uint256) returns(bytes32,uint128,uint128)' "${STARTING_OUTPUT_INDEX}") +STARTING_OUTPUT_ROOT=$(echo ${OUTPUT} | cut -d' ' -f 1) +L2_HEAD_NUMBER=$(echo ${OUTPUT} | cut -d' ' -f 3) +L2_HEAD=$(cast block "${L2_HEAD_NUMBER}" --rpc-url "${L2RPC}" -f hash) + +TODAY=$(date +"%Y-%m-%d-%H-%M-%S") +FILENAME=${TODAY}-op-program-data-log.sh +OP_PROGRAM_DATA_DIR=$(pwd)/op-program-db-sepolia-${TODAY} + +echo "export L1_HEAD=${L1_HEAD}" >> ${FILENAME} +echo "export L2_HEAD=${L2_HEAD}" >> ${FILENAME} +echo "export L2_BLOCK_NUMBER=${L2_BLOCK_NUMBER}" >> ${FILENAME} +echo "export STARTING_OUTPUT_ROOT=${STARTING_OUTPUT_ROOT}" >> ${FILENAME} +echo "export L2_CLAIM=${L2_CLAIM}" >> ${FILENAME} +echo "export OP_PROGRAM_DATA_DIR=${OP_PROGRAM_DATA_DIR}" >> ${FILENAME} +echo "export L1RPC=${L1RPC}" >> ${FILENAME} +echo "export L2RPC=${L2RPC}" >> ${FILENAME} + +echo "${FILENAME}" diff --git a/optimism/run-code.sh b/optimism/run-code.sh index 43cd300fe2..1af79e85d9 100755 --- a/optimism/run-code.sh +++ b/optimism/run-code.sh @@ -3,48 +3,8 @@ set -euo pipefail source rpcs.sh -# L2 output oracle on Goerli -# L2_OUTPUT_ORACLE=0xE6Dfba0953616Bacab0c9A8ecb3a9BBa77FC15c0 -# L2 output oracle on Sepolia -L2_OUTPUT_ORACLE=0x90E9c4f8a994a250F6aEfd61CAFb4F2e895D458F +FILENAME="$(./generate-config.sh)" -L2_FINALIZED_NUMBER=$(cast block finalized --rpc-url "${L2RPC}" -f number) -echo "Finalize number: ${L2_FINALIZED_NUMBER}" -L2_FINALIZED_HASH=$(cast block "${L2_FINALIZED_NUMBER}" --rpc-url "${L2RPC}" -f hash) - -L1_FINALIZED_NUMBER=$(cast block finalized --rpc-url "${L1RPC}" -f number) -L1_FINALIZED_HASH=$(cast block "${L1_FINALIZED_NUMBER}" --rpc-url "${L1RPC}" -f hash) - -OUTPUT_INDEX=$(cast call --rpc-url "${L1RPC}" "${L2_OUTPUT_ORACLE}" 'getL2OutputIndexAfter(uint256) returns(uint256)' "${L2_FINALIZED_NUMBER}") -OUTPUT_INDEX=$((OUTPUT_INDEX-1)) - -OUTPUT=$(cast call --rpc-url "${L1RPC}" "${L2_OUTPUT_ORACLE}" 'getL2Output(uint256) returns(bytes32,uint128,uint128)' "${OUTPUT_INDEX}") -OUTPUT_ROOT=$(echo ${OUTPUT} | cut -d' ' -f 1) -OUTPUT_TIMESTAMP=$(echo ${OUTPUT} | cut -d' ' -f 2) -OUTPUT_L2BLOCK_NUMBER=$(echo ${OUTPUT} | cut -d' ' -f 3) - -export L1_HEAD=$L1_FINALIZED_HASH -export L2_CLAIM=$OUTPUT_ROOT -export L2_BLOCK_NUMBER=$OUTPUT_L2BLOCK_NUMBER - -STARTING_L2BLOCK_NUMBER=$((L2_BLOCK_NUMBER-100)) -STARTING_OUTPUT_INDEX=$(cast call --rpc-url "${L1RPC}" "${L2_OUTPUT_ORACLE}" 'getL2OutputIndexAfter(uint256) returns(uint256)' "${STARTING_L2BLOCK_NUMBER}") -STARTING_OUTPUT=$(cast call --rpc-url "${L1RPC}" "${L2_OUTPUT_ORACLE}" 'getL2Output(uint256) returns(bytes32,uint128,uint128)' "${STARTING_OUTPUT_INDEX}") -export STARTING_OUTPUT_ROOT=$(echo ${OUTPUT} | cut -d' ' -f 1) -L2_HEAD_NUMBER=$(echo ${OUTPUT} | cut -d' ' -f 3) -export L2_HEAD=$(cast block "${L2_HEAD_NUMBER}" --rpc-url "${L2RPC}" -f hash) - -TODAY=$(date +"%Y-%m-%d-%H-%M-%S") -FILENAME=${TODAY}-op-program-data-log.sh -export OP_PROGRAM_DATA_DIR=$(pwd)/op-program-db-sepolia-${TODAY} - -echo "export L1_HEAD=${L1_HEAD}" >> ${FILENAME} -echo "export L2_HEAD=${L2_HEAD}" >> ${FILENAME} -echo "export L2_BLOCK_NUMBER=${L2_BLOCK_NUMBER}" >> ${FILENAME} -echo "export STARTING_OUTPUT_ROOT=${STARTING_OUTPUT_ROOT}" >> ${FILENAME} -echo "export L2_CLAIM=${L2_CLAIM}" >> ${FILENAME} -echo "export OP_PROGRAM_DATA_DIR=${OP_PROGRAM_DATA_DIR}" >> ${FILENAME} -echo "export L1RPC=${L1RPC}" >> ${FILENAME} -echo "export L2RPC=${L2RPC}" >> ${FILENAME} +source $FILENAME ./run-op-program.sh From 7af8026becbf24924e4a27a79004ec68fe55731f Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Mon, 23 Oct 2023 18:24:29 +0100 Subject: [PATCH 06/13] Add cannon to runner --- optimism/run-op-program.sh | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/optimism/run-op-program.sh b/optimism/run-op-program.sh index f7936fee6e..c16072e8c9 100755 --- a/optimism/run-op-program.sh +++ b/optimism/run-op-program.sh @@ -2,6 +2,7 @@ set -euo pipefail make -C ./ethereum-optimism/op-program op-program +make -C ./ethereum-optimism/cannon cannon set -x ./ethereum-optimism/op-program/bin/op-program \ @@ -15,3 +16,24 @@ set -x --l2.outputroot $STARTING_OUTPUT_ROOT \ --l2.claim $L2_CLAIM \ --l2.blocknumber $L2_BLOCK_NUMBER + +./ethereum-optimism/cannon/bin/cannon load-elf --path=./ethereum-optimism/op-program/bin/op-program-client.elf + +./ethereum-optimism/cannon/bin/cannon run \ + --pprof.cpu \ + --info-at '%10000000' \ + --proof-at never \ + --input ./state.json \ + -- \ + ./ethereum-optimism/op-program/bin/op-program \ + --log.level DEBUG \ + --l1 ${L1RPC} \ + --l2 ${L2RPC} \ + --network sepolia \ + --datadir ${OP_PROGRAM_DATA_DIR} \ + --l1.head ${L1_HEAD} \ + --l2.head ${L2_HEAD} \ + --l2.outputroot ${STARTING_OUTPUT_ROOT} \ + --l2.claim ${L2_CLAIM} \ + --l2.blocknumber ${L2_BLOCK_NUMBER} \ + --server From 85841b02ac2b08b17bb66a86ef5293148ea3fadf Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Mon, 23 Oct 2023 18:27:30 +0100 Subject: [PATCH 07/13] Allow an explicit filename to override --- optimism/run-code.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/optimism/run-code.sh b/optimism/run-code.sh index 1af79e85d9..a07555070f 100755 --- a/optimism/run-code.sh +++ b/optimism/run-code.sh @@ -3,7 +3,11 @@ set -euo pipefail source rpcs.sh -FILENAME="$(./generate-config.sh)" +set +u +if [ -z "${FILENAME}" ]; then + FILENAME="$(./generate-config.sh)" +fi +set -u source $FILENAME From d2aac11e5582a26bb7b26c68f721ddef0ccad09b Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Tue, 24 Oct 2023 15:22:51 +0100 Subject: [PATCH 08/13] Import parsing for CLI --- Cargo.lock | 21 ++++---- optimism/Cargo.toml | 1 + optimism/src/cannon.rs | 118 ++++++++++++++++++++++++++++++++++++++++ optimism/src/lib.rs | 1 + optimism/src/main.rs | 119 ++++++++++++++++++++++++++++++++++++++++- 5 files changed, 249 insertions(+), 11 deletions(-) create mode 100644 optimism/src/cannon.rs diff --git a/Cargo.lock b/Cargo.lock index 8028b4f6d9..03396e2f2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1260,6 +1260,7 @@ dependencies = [ "mina-curves", "mina-poseidon", "poly-commitment", + "regex", "rmp-serde", "serde", "serde_json", @@ -1325,9 +1326,9 @@ checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" @@ -2100,25 +2101,25 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax 0.7.3", + "regex-syntax 0.8.2", ] [[package]] name = "regex-automata" -version = "0.3.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d3daa6976cffb758ec878f108ba0e062a45b2d6ca3a2cca965338855476caf" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.3", + "regex-syntax 0.8.2", ] [[package]] @@ -2129,9 +2130,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab07dc67230e4a4718e70fd5c20055a4334b121f1f9db8fe63ef39ce9b8c846" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rmp" diff --git a/optimism/Cargo.toml b/optimism/Cargo.toml index 9b45ab1d29..f1edb563cd 100644 --- a/optimism/Cargo.toml +++ b/optimism/Cargo.toml @@ -27,3 +27,4 @@ ark-poly = { version = "0.3.0", features = [ "parallel" ] } ark-ff = { version = "0.3.0", features = [ "parallel" ] } clap = "4.4.6" hex = "0.4.3" +regex = "1.10.2" diff --git a/optimism/src/cannon.rs b/optimism/src/cannon.rs new file mode 100644 index 0000000000..c7693f3cab --- /dev/null +++ b/optimism/src/cannon.rs @@ -0,0 +1,118 @@ +// Data structure and stuff for compatibility with Cannon + +use regex::Regex; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug)] +pub struct Page { + pub index: u32, + pub data: String, +} + +// The renaming below keeps compatibility with OP Cannon's state format +#[derive(Serialize, Deserialize, Debug)] +pub struct State { + pub memory: Vec, + #[serde(rename = "preimageKey")] + pub preimage_key: String, + #[serde(rename = "preimageOffset")] + pub preimage_offset: u32, + pub pc: u32, + #[serde(rename = "nextPC")] + next_pc: u32, // + pub lo: u32, + pub hi: u32, + pub heap: u32, + exit: u8, + pub exited: bool, + pub step: u64, + pub registers: [u32; 32], + pub last_hint: Option>, +} + +#[derive(Clone, Debug, PartialEq)] +pub enum StepFrequency { + Never, + Always, + Exactly(u64), + Every(u64), +} + +// Simple parser for Cannon's "frequency format" +// A frequency input is either +// - never/always +// - = (only at step n) +// - % (every steps multiple of n) +pub fn step_frequency_parser(s: &str) -> std::result::Result { + use StepFrequency::*; + + let mod_re = Regex::new(r"%([0-9]+)").unwrap(); + let eq_re = Regex::new(r"=([0-9]+)").unwrap(); + + match s { + "never" => Ok(Never), + "always" => Ok(Always), + s => { + if let Some(m) = mod_re.captures(s) { + Ok(Every(m[1].parse::().unwrap())) + } else if let Some(m) = eq_re.captures(s) { + Ok(Exactly(m[1].parse::().unwrap())) + } else { + Err(format!("Unknown frequency format {}", s)) + } + } + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn sp_parser() { + use StepFrequency::*; + assert_eq!(step_frequency_parser("never"), Ok(Never)); + assert_eq!(step_frequency_parser("always"), Ok(Always)); + assert_eq!(step_frequency_parser("=123"), Ok(Exactly(123))); + assert_eq!(step_frequency_parser("%123"), Ok(Every(123))); + assert!(step_frequency_parser("@123").is_err()); + } +} + +impl ToString for State { + // A very debatable and incomplete, but serviceable, `to_string` implementation. + fn to_string(&self) -> String { + format!( + "memory_size (length): {}\nfirst page size: {}\npreimage key: {}\npreimage offset:{}\npc: {}\nlo: {}\nhi: {}\nregisters:{:#?} ", + self.memory.len(), + self.memory[0].data.len(), + self.preimage_key, + self.preimage_offset, + self.pc, + self.lo, + self.hi, + self.registers + ) + } +} + +#[derive(Debug)] +pub struct HostProgram { + pub name: String, + pub arguments: Vec, +} + +#[derive(Debug)] +pub struct VmConfiguration { + pub input_state_file: String, + pub output_state_file: String, + pub metadata_file: String, + pub proof_at: StepFrequency, + pub stop_at: StepFrequency, + pub info_at: StepFrequency, + pub proof_fmt: String, + pub snapshot_fmt: String, + pub pprof_cpu: bool, + pub host: Option, +} diff --git a/optimism/src/lib.rs b/optimism/src/lib.rs index e69de29bb2..3bec498068 100644 --- a/optimism/src/lib.rs +++ b/optimism/src/lib.rs @@ -0,0 +1 @@ +pub mod cannon; diff --git a/optimism/src/main.rs b/optimism/src/main.rs index 9301ced20f..f7692547cf 100644 --- a/optimism/src/main.rs +++ b/optimism/src/main.rs @@ -1,6 +1,123 @@ -use std:: process::ExitCode; +use clap::{arg, value_parser, Arg, ArgAction, Command}; +use kimchi_optimism::cannon::VmConfiguration; +use std::process::ExitCode; + +fn cli() -> VmConfiguration { + use kimchi_optimism::cannon::*; + + let app_name = "zkvm"; + let cli = Command::new(app_name) + .version("0.1") + .about("MIPS-based zkvm") + .arg(arg!(--input "initial state file").default_value("state.json")) + .arg(arg!(--output "output state file").default_value("out.json")) + .arg(arg!(--meta "metadata file").default_value("meta.json")) + // The CLI arguments below this line are ignored at this point + .arg( + Arg::new("proof-at") + .short('p') + .long("proof-at") + .value_name("FREQ") + .default_value("never") + .value_parser(step_frequency_parser), + ) + .arg( + Arg::new("proof-fmt") + .long("proof-fmt") + .value_name("FORMAT") + .default_value("proof-%d.json"), + ) + .arg( + Arg::new("snapshot-fmt") + .long("snapshot-fmt") + .value_name("FORMAT") + .default_value("state-%d.json"), + ) + .arg( + Arg::new("stop-at") + .long("stop-at") + .value_name("FREQ") + .default_value("never") + .value_parser(step_frequency_parser), + ) + .arg( + Arg::new("info-at") + .long("info-at") + .value_name("FREQ") + .default_value("never") + .value_parser(step_frequency_parser), + ) + .arg( + Arg::new("pprof-cpu") + .long("pprof-cpu") + .action(ArgAction::SetTrue), + ) + .arg( + arg!(host: [HOST] "host program specification [host program arguments]") + .num_args(1..) + .last(true) + .value_parser(value_parser!(String)), + ); + + let cli = cli.get_matches(); + + let input_state_file = cli + .get_one::("input") + .expect("Default ensures there is always a value"); + + let output_state_file = cli + .get_one::("output") + .expect("Default ensures there is always a value"); + + let metadata_file = cli + .get_one::("meta") + .expect("Default ensures there is always a value"); + + let proof_at = cli.get_one::("proof-at").expect(""); + let info_at = cli.get_one::("info-at").expect(""); + let stop_at = cli.get_one::("stop-at").expect(""); + + let proof_fmt = cli.get_one::("proof-fmt").expect(""); + let snapshot_fmt = cli.get_one::("snapshot-fmt").expect(""); + let pprof_cpu = cli.get_one::("pprof-cpu").expect(""); + + let host_spec = cli + .get_many::("host") + .map(|vals| vals.collect::>()) + .unwrap_or_default(); + + let host = if host_spec.is_empty() { + None + } else { + Some(HostProgram { + name: host_spec[0].to_string(), + arguments: host_spec[1..] + .to_vec() + .iter() + .map(|x| x.to_string()) + .collect(), + }) + }; + + VmConfiguration { + input_state_file: input_state_file.to_string(), + output_state_file: output_state_file.to_string(), + metadata_file: metadata_file.to_string(), + proof_at: proof_at.clone(), + stop_at: stop_at.clone(), + info_at: info_at.clone(), + proof_fmt: proof_fmt.to_string(), + snapshot_fmt: snapshot_fmt.to_string(), + pprof_cpu: *pprof_cpu, + host, + } +} pub fn main() -> ExitCode { + let configuration = cli(); + + println!("configuration\n{:#?}", configuration); + // TODO: Logic ExitCode::FAILURE } From 1cd783279528a05bb1fea7d2756fc72bf745ca40 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Tue, 24 Oct 2023 15:31:10 +0100 Subject: [PATCH 09/13] Load the state declared in the flags --- optimism/src/main.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/optimism/src/main.rs b/optimism/src/main.rs index f7692547cf..6989806a70 100644 --- a/optimism/src/main.rs +++ b/optimism/src/main.rs @@ -1,6 +1,6 @@ use clap::{arg, value_parser, Arg, ArgAction, Command}; -use kimchi_optimism::cannon::VmConfiguration; -use std::process::ExitCode; +use kimchi_optimism::cannon::{State, VmConfiguration}; +use std::{fs::File, io::BufReader, process::ExitCode}; fn cli() -> VmConfiguration { use kimchi_optimism::cannon::*; @@ -118,6 +118,23 @@ pub fn main() -> ExitCode { println!("configuration\n{:#?}", configuration); + let file = File::open(configuration.input_state_file).expect("file"); + + let reader = BufReader::new(file); + // Read the JSON contents of the file as an instance of `State`. + let state: State = serde_json::from_reader(reader).expect("Error reading input state file"); + + if let Some(host_program) = configuration.host { + println!("Launching host program {}", host_program.name); + + let _child = std::process::Command::new(host_program.name) + .args(host_program.arguments) + .spawn() + .expect("Could not spawn host process"); + }; + + println!("{}", state.to_string()); + // TODO: Logic ExitCode::FAILURE } From 391ea4e2b14d63da72a9fc2eddf812dfc47878a3 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Tue, 24 Oct 2023 15:34:13 +0100 Subject: [PATCH 10/13] Run the VM CLI from the main script --- optimism/run-code.sh | 2 ++ optimism/run-vm.sh | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100755 optimism/run-vm.sh diff --git a/optimism/run-code.sh b/optimism/run-code.sh index a07555070f..c664e58025 100755 --- a/optimism/run-code.sh +++ b/optimism/run-code.sh @@ -12,3 +12,5 @@ set -u source $FILENAME ./run-op-program.sh + +./run-vm.sh diff --git a/optimism/run-vm.sh b/optimism/run-vm.sh new file mode 100755 index 0000000000..4f24506b4e --- /dev/null +++ b/optimism/run-vm.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -euo pipefail + +cargo run -p kimchi_optimism -- \ + --pprof-cpu \ + --info-at '%10000000' \ + --proof-at never \ + --input ./state.json \ + -- \ + ./ethereum-optimism/op-program/bin/op-program \ + --log.level DEBUG \ + --l1 ${L1RPC} \ + --l2 ${L2RPC} \ + --network sepolia \ + --datadir ${OP_PROGRAM_DATA_DIR} \ + --l1.head ${L1_HEAD} \ + --l2.head ${L2_HEAD} \ + --l2.outputroot ${STARTING_OUTPUT_ROOT} \ + --l2.claim ${L2_CLAIM} \ + --l2.blocknumber ${L2_BLOCK_NUMBER} \ + --server From 5ab1b2d6a990dc06f6b630d7d832eb60ba4af630 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Tue, 24 Oct 2023 17:41:16 +0100 Subject: [PATCH 11/13] Use unwrap instead of empty string expects --- optimism/src/main.rs | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/optimism/src/main.rs b/optimism/src/main.rs index 6989806a70..32c86b9f9e 100644 --- a/optimism/src/main.rs +++ b/optimism/src/main.rs @@ -61,25 +61,19 @@ fn cli() -> VmConfiguration { let cli = cli.get_matches(); - let input_state_file = cli - .get_one::("input") - .expect("Default ensures there is always a value"); + let input_state_file = cli.get_one::("input").unwrap(); - let output_state_file = cli - .get_one::("output") - .expect("Default ensures there is always a value"); + let output_state_file = cli.get_one::("output").unwrap(); - let metadata_file = cli - .get_one::("meta") - .expect("Default ensures there is always a value"); + let metadata_file = cli.get_one::("meta").unwrap(); - let proof_at = cli.get_one::("proof-at").expect(""); - let info_at = cli.get_one::("info-at").expect(""); - let stop_at = cli.get_one::("stop-at").expect(""); + let proof_at = cli.get_one::("proof-at").unwrap(); + let info_at = cli.get_one::("info-at").unwrap(); + let stop_at = cli.get_one::("stop-at").unwrap(); - let proof_fmt = cli.get_one::("proof-fmt").expect(""); - let snapshot_fmt = cli.get_one::("snapshot-fmt").expect(""); - let pprof_cpu = cli.get_one::("pprof-cpu").expect(""); + let proof_fmt = cli.get_one::("proof-fmt").unwrap(); + let snapshot_fmt = cli.get_one::("snapshot-fmt").unwrap(); + let pprof_cpu = cli.get_one::("pprof-cpu").unwrap(); let host_spec = cli .get_many::("host") @@ -118,7 +112,7 @@ pub fn main() -> ExitCode { println!("configuration\n{:#?}", configuration); - let file = File::open(configuration.input_state_file).expect("file"); + let file = File::open(configuration.input_state_file).expect("Error opening input state file "); let reader = BufReader::new(file); // Read the JSON contents of the file as an instance of `State`. From a5f48d1dab3d23a4d26369697814cc05f3248307 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Tue, 24 Oct 2023 17:48:06 +0100 Subject: [PATCH 12/13] Mini readme --- optimism/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 optimism/README.md diff --git a/optimism/README.md b/optimism/README.md new file mode 100644 index 0000000000..2dbf25c375 --- /dev/null +++ b/optimism/README.md @@ -0,0 +1,18 @@ +To run the demo: +* create an executable file `rpcs.sh` that looks like + ```bash + #!/usr/bin/env bash + export L1RPC=http://xxxxxxxxx + export L2RPC=http://xxxxxxxxx + ``` +* run the `run-code.sh` script. + +This will +* generate the initial state, +* execute the OP program, +* execute the OP program through the cannon MIPS VM, +* execute the OP program through the kimchi MIPS VM prover. + +The initial state will be output to a file with format `YYYY-MM-DD-HH-MM-SS-op-program-data-log.sh`. + +If you want to re-run against an existing state, pass the environment variable `FILENAME=YYYY-MM-DD-HH-MM-SS-op-program-data-log.sh` to the `run-code.sh` script. From c7254f725b5a802d53853232cc0680f8d03c44d1 Mon Sep 17 00:00:00 2001 From: mrmr1993 Date: Tue, 24 Oct 2023 17:49:01 +0100 Subject: [PATCH 13/13] Update script to use env --- optimism/generate-config.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/optimism/generate-config.sh b/optimism/generate-config.sh index e71f8a90ed..3e8dae0221 100755 --- a/optimism/generate-config.sh +++ b/optimism/generate-config.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail source rpcs.sh