diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fe26b1044b..b9fcfba7fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -141,24 +141,54 @@ jobs: echo "GOMEMLIMIT=6GiB" >> "$GITHUB_ENV" echo "GOGC=80" >> "$GITHUB_ENV" - - name: run tests without race detection + - name: run tests without race detection and path state scheme if: matrix.test-mode == 'defaults' + env: + TEST_STATE_SCHEME: path run: | packages=`go list ./...` for package in $packages; do echo running tests for $package - if ! stdbuf -oL gotestsum --format short-verbose --packages="$package" --rerun-fails=1 --no-color=false -- -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,./go-ethereum/... -timeout 20m -tags=cionly > >(stdbuf -oL tee -a full.log | grep -vE "INFO|seal"); then + if ! stdbuf -oL gotestsum --format short-verbose --packages="$package" --rerun-fails=2 --no-color=false -- -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,./go-ethereum/... -timeout 20m -tags=cionly > >(stdbuf -oL tee -a full.log | grep -vE "INFO|seal"); then exit 1 fi done - - name: run tests with race detection + - name: run tests without race detection and hash state scheme + if: matrix.test-mode == 'defaults' + env: + TEST_STATE_SCHEME: hash + run: | + packages=`go list ./...` + for package in $packages; do + echo running tests for $package + if ! stdbuf -oL gotestsum --format short-verbose --packages="$package" --rerun-fails=2 --no-color=false -- -timeout 20m -tags=cionly; then + exit 1 + fi + done + + - name: run tests with race detection and path state scheme if: matrix.test-mode == 'race' + env: + TEST_STATE_SCHEME: path run: | packages=`go list ./...` for package in $packages; do echo running tests for $package - if ! stdbuf -oL gotestsum --format short-verbose --packages="$package" --rerun-fails=1 --no-color=false -- -race -timeout 30m > >(stdbuf -oL tee -a full.log | grep -vE "INFO|seal"); then + if ! stdbuf -oL gotestsum --format short-verbose --packages="$package" --rerun-fails=2 --no-color=false -- -race -timeout 30m > >(stdbuf -oL tee -a full.log | grep -vE "INFO|seal"); then + exit 1 + fi + done + + - name: run tests with race detection and hash state scheme + if: matrix.test-mode == 'race' + env: + TEST_STATE_SCHEME: hash + run: | + packages=`go list ./...` + for package in $packages; do + echo running tests for $package + if ! stdbuf -oL gotestsum --format short-verbose --packages="$package" --rerun-fails=2 --no-color=false -- -race -timeout 30m; then exit 1 fi done @@ -173,7 +203,7 @@ jobs: packages=`go list ./...` for package in $packages; do echo running tests for $package - if ! stdbuf -oL gotestsum --format short-verbose --packages="$package" --rerun-fails=1 --no-color=false -- -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,./go-ethereum/... -tags=challengetest -run=TestChallenge > >(stdbuf -oL tee -a full.log | grep -vE "INFO|seal"); then + if ! stdbuf -oL gotestsum --format short-verbose --packages="$package" --rerun-fails=2 --no-color=false -- -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,./go-ethereum/... -tags=challengetest -run=TestChallenge > >(stdbuf -oL tee -a full.log | grep -vE "INFO|seal"); then exit 1 fi done @@ -184,7 +214,7 @@ jobs: packages=`go list ./...` for package in $packages; do echo running tests for $package - if ! stdbuf -oL gotestsum --format short-verbose --packages="$package" --rerun-fails=1 --no-color=false -- -timeout 60m -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,./go-ethereum/... -tags=stylustest -run="TestProgramArbitrator" > >(stdbuf -oL tee -a full.log | grep -vE "INFO|seal"); then + if ! stdbuf -oL gotestsum --format short-verbose --packages="$package" --rerun-fails=2 --no-color=false -- -timeout 60m -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,./go-ethereum/... -tags=stylustest -run="TestProgramArbitrator" > >(stdbuf -oL tee -a full.log | grep -vE "INFO|seal"); then exit 1 fi done @@ -195,7 +225,7 @@ jobs: packages=`go list ./...` for package in $packages; do echo running tests for $package - if ! stdbuf -oL gotestsum --format short-verbose --packages="$package" --rerun-fails=1 --no-color=false -- -timeout 60m -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,./go-ethereum/... -tags=stylustest -run="TestProgramLong" > >(stdbuf -oL tee -a full.log | grep -vE "INFO|seal"); then + if ! stdbuf -oL gotestsum --format short-verbose --packages="$package" --rerun-fails=2 --no-color=false -- -timeout 60m -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,./go-ethereum/... -tags=stylustest -run="TestProgramLong" > >(stdbuf -oL tee -a full.log | grep -vE "INFO|seal"); then exit 1 fi done @@ -214,4 +244,3 @@ jobs: files: ./coverage.txt,./coverage-redis.txt verbose: false token: ${{ secrets.CODECOV_TOKEN }} - diff --git a/Dockerfile b/Dockerfile index 22ac262f52..6383a2c0cb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -103,6 +103,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ COPY arbitrator/Cargo.* arbitrator/ COPY ./Makefile ./ COPY arbitrator/arbutil arbitrator/arbutil +COPY arbitrator/bench arbitrator/bench COPY arbitrator/brotli arbitrator/brotli COPY arbitrator/caller-env arbitrator/caller-env COPY arbitrator/prover arbitrator/prover @@ -131,9 +132,12 @@ RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - && \ COPY --from=brotli-library-export / target/ COPY arbitrator/Cargo.* arbitrator/ COPY arbitrator/arbutil arbitrator/arbutil +COPY arbitrator/bench arbitrator/bench COPY arbitrator/brotli arbitrator/brotli COPY arbitrator/caller-env arbitrator/caller-env COPY arbitrator/prover/Cargo.toml arbitrator/prover/ +COPY arbitrator/prover/benches arbitrator/prover/benches +COPY arbitrator/bench/Cargo.toml arbitrator/bench/ COPY arbitrator/jit/Cargo.toml arbitrator/jit/ COPY arbitrator/stylus/Cargo.toml arbitrator/stylus/ COPY arbitrator/tools/wasmer arbitrator/tools/wasmer @@ -141,11 +145,15 @@ COPY arbitrator/wasm-libraries/user-host-trait/Cargo.toml arbitrator/wasm-librar RUN bash -c 'mkdir arbitrator/{prover,jit,stylus}/src arbitrator/wasm-libraries/user-host-trait/src' RUN echo "fn test() {}" > arbitrator/jit/src/lib.rs && \ echo "fn test() {}" > arbitrator/prover/src/lib.rs && \ + echo "fn test() {}" > arbitrator/bench/src/lib.rs && \ + echo "fn test() {}" > arbitrator/prover/benches/merkle_bench.rs && \ echo "fn test() {}" > arbitrator/stylus/src/lib.rs && \ echo "fn test() {}" > arbitrator/wasm-libraries/user-host-trait/src/lib.rs && \ cargo build --manifest-path arbitrator/Cargo.toml --release --lib && \ rm arbitrator/prover/src/lib.rs arbitrator/jit/src/lib.rs arbitrator/stylus/src/lib.rs && \ - rm arbitrator/wasm-libraries/user-host-trait/src/lib.rs + rm arbitrator/wasm-libraries/user-host-trait/src/lib.rs && \ + rm arbitrator/prover/benches/merkle_bench.rs && \ + rm arbitrator/bench/src/lib.rs COPY ./Makefile ./ COPY arbitrator/prover arbitrator/prover COPY arbitrator/wasm-libraries arbitrator/wasm-libraries diff --git a/Makefile b/Makefile index b0d8116c97..977044da59 100644 --- a/Makefile +++ b/Makefile @@ -428,10 +428,10 @@ $(stylus_test_erc20_wasm): $(stylus_test_erc20_src) @touch -c $@ # cargo might decide to not rebuild the binary contracts/test/prover/proofs/float%.json: $(arbitrator_cases)/float%.wasm $(prover_bin) $(output_latest)/soft-float.wasm - $(prover_bin) $< -l $(output_latest)/soft-float.wasm -o $@ -b --allow-hostapi --require-success --always-merkleize + $(prover_bin) $< -l $(output_latest)/soft-float.wasm -o $@ -b --allow-hostapi --require-success contracts/test/prover/proofs/no-stack-pollution.json: $(arbitrator_cases)/no-stack-pollution.wasm $(prover_bin) - $(prover_bin) $< -o $@ --allow-hostapi --require-success --always-merkleize + $(prover_bin) $< -o $@ --allow-hostapi --require-success target/testdata/preimages.bin: mkdir -p `dirname $@` @@ -455,19 +455,19 @@ contracts/test/prover/proofs/global-state.json: echo "[]" > $@ contracts/test/prover/proofs/forward-test.json: $(arbitrator_cases)/forward-test.wasm $(arbitrator_tests_forward_deps) $(prover_bin) - $(prover_bin) $< -o $@ --allow-hostapi --always-merkleize $(patsubst %,-l %, $(arbitrator_tests_forward_deps)) + $(prover_bin) $< -o $@ --allow-hostapi $(patsubst %,-l %, $(arbitrator_tests_forward_deps)) contracts/test/prover/proofs/link.json: $(arbitrator_cases)/link.wasm $(arbitrator_tests_link_deps) $(prover_bin) - $(prover_bin) $< -o $@ --allow-hostapi --always-merkleize --stylus-modules $(arbitrator_tests_link_deps) --require-success + $(prover_bin) $< -o $@ --allow-hostapi --stylus-modules $(arbitrator_tests_link_deps) --require-success contracts/test/prover/proofs/dynamic.json: $(patsubst %,$(arbitrator_cases)/%.wasm, dynamic user) $(prover_bin) - $(prover_bin) $< -o $@ --allow-hostapi --always-merkleize --stylus-modules $(arbitrator_cases)/user.wasm --require-success + $(prover_bin) $< -o $@ --allow-hostapi --stylus-modules $(arbitrator_cases)/user.wasm --require-success contracts/test/prover/proofs/bulk-memory.json: $(patsubst %,$(arbitrator_cases)/%.wasm, bulk-memory) $(prover_bin) - $(prover_bin) $< -o $@ --allow-hostapi --always-merkleize --stylus-modules $(arbitrator_cases)/user.wasm -b + $(prover_bin) $< -o $@ --allow-hostapi --stylus-modules $(arbitrator_cases)/user.wasm -b contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(prover_bin) - $(prover_bin) $< -o $@ --allow-hostapi --always-merkleize + $(prover_bin) $< -o $@ --allow-hostapi # strategic rules to minimize dependency building diff --git a/arbitrator/Cargo.lock b/arbitrator/Cargo.lock index a89dc5e97e..01774c0c4d 100644 --- a/arbitrator/Cargo.lock +++ b/arbitrator/Cargo.lock @@ -55,6 +55,27 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + [[package]] name = "ansi_term" version = "0.12.1" @@ -64,6 +85,55 @@ dependencies = [ "winapi", ] +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "arbitrary" version = "1.3.2" @@ -127,6 +197,27 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bench" +version = "0.1.0" +dependencies = [ + "arbutil", + "clap 4.5.4", + "eyre", + "gperftools", + "hex", + "prover", + "serde", + "serde_json", + "serde_with 3.8.1", +] + [[package]] name = "bincode" version = "1.3.3" @@ -156,6 +247,7 @@ checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", + "serde", "tap", "wyz", ] @@ -281,6 +373,12 @@ dependencies = [ "wasmer", ] +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cc" version = "1.0.98" @@ -304,6 +402,46 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets", +] + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "clap" version = "2.34.0" @@ -319,12 +457,64 @@ dependencies = [ "vec_map", ] +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim 0.11.1", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + [[package]] name = "convert_case" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + [[package]] name = "corosensei" version = "0.1.4" @@ -430,6 +620,42 @@ version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb" +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap 4.5.4", + "criterion-plot", + "is-terminal", + "itertools", + "num-traits", + "once_cell", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools", +] + [[package]] name = "crossbeam-deque" version = "0.8.5" @@ -524,6 +750,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", + "strsim 0.11.1", "syn 2.0.66", ] @@ -562,6 +789,16 @@ dependencies = [ "parking_lot_core", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + [[package]] name = "derivative" version = "2.2.0" @@ -643,7 +880,16 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6" dependencies = [ - "enum-iterator-derive", + "enum-iterator-derive 0.7.0", +] + +[[package]] +name = "enum-iterator" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c280b9e6b3ae19e152d8e31cf47f18389781e119d4013a2a2bb0180e5facc635" +dependencies = [ + "enum-iterator-derive 1.4.0", ] [[package]] @@ -657,6 +903,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "enum-iterator-derive" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "enumset" version = "1.1.3" @@ -684,6 +941,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "error-chain" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" +dependencies = [ + "backtrace", + "version_check", +] + [[package]] name = "eyre" version = "0.6.12" @@ -765,6 +1032,27 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "gperftools" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20a3fc5818b1223ec628fc6998c8900486208b577f78c07500d4b52f983ebc9d" +dependencies = [ + "error-chain", + "lazy_static", + "pkg-config", +] + +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if 1.0.0", + "crunchy", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -793,6 +1081,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -813,6 +1107,32 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] [[package]] name = "ident_case" @@ -834,6 +1154,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", + "serde", ] [[package]] @@ -844,6 +1165,7 @@ checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.5", + "serde", ] [[package]] @@ -871,6 +1193,23 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "is-terminal" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.10.5" @@ -1136,6 +1475,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-derive" version = "0.4.2" @@ -1242,6 +1587,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + [[package]] name = "opaque-debug" version = "0.3.1" @@ -1277,6 +1628,46 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "plotters" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" + +[[package]] +name = "plotters-svg" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1331,10 +1722,13 @@ version = "0.1.0" dependencies = [ "arbutil", "bincode", + "bitvec", "brotli", "c-kzg", + "criterion", "derivative", "digest 0.9.0", + "enum-iterator 2.1.0", "eyre", "fnv", "hex", @@ -1349,11 +1743,12 @@ dependencies = [ "num-traits", "once_cell", "parking_lot", + "rand", "rayon", "rustc-demangle", "serde", "serde_json", - "serde_with", + "serde_with 1.14.0", "sha2 0.9.9", "sha3 0.9.1", "smallvec", @@ -1600,6 +1995,15 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -1673,7 +2077,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" dependencies = [ "serde", - "serde_with_macros", + "serde_with_macros 1.5.2", +] + +[[package]] +name = "serde_with" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.6", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros 3.8.1", + "time", ] [[package]] @@ -1688,6 +2110,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "serde_with_macros" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +dependencies = [ + "darling 0.20.9", + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "sha2" version = "0.9.9" @@ -1795,13 +2229,19 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "structopt" version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" dependencies = [ - "clap", + "clap 2.34.0", "lazy_static", "structopt-derive", ] @@ -1812,7 +2252,7 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro-error", "proc-macro2", "quote", @@ -1920,6 +2360,37 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tiny-keccak" version = "2.0.2" @@ -1929,6 +2400,16 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -2027,6 +2508,12 @@ dependencies = [ "ruint2", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "uuid" version = "1.8.0" @@ -2045,6 +2532,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -2148,7 +2645,7 @@ dependencies = [ "backtrace", "bytes", "cfg-if 1.0.0", - "enum-iterator", + "enum-iterator 0.7.0", "enumset", "lazy_static", "leb128", @@ -2237,7 +2734,7 @@ name = "wasmer-types" version = "4.2.8" dependencies = [ "bytecheck", - "enum-iterator", + "enum-iterator 0.7.0", "enumset", "indexmap 1.9.3", "more-asserts", @@ -2257,7 +2754,7 @@ dependencies = [ "crossbeam-queue", "dashmap", "derivative", - "enum-iterator", + "enum-iterator 0.7.0", "fnv", "indexmap 1.9.3", "lazy_static", @@ -2304,6 +2801,16 @@ dependencies = [ "wast", ] +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "wee_alloc" version = "0.4.5" @@ -2332,12 +2839,30 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.33.0" diff --git a/arbitrator/Cargo.toml b/arbitrator/Cargo.toml index 138bdc2c69..94ca08b0b5 100644 --- a/arbitrator/Cargo.toml +++ b/arbitrator/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ "arbutil", + "bench", "brotli", "brotli/fuzz", "caller-env", diff --git a/arbitrator/bench/Cargo.toml b/arbitrator/bench/Cargo.toml new file mode 100644 index 0000000000..3ab5b99b08 --- /dev/null +++ b/arbitrator/bench/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "bench" +version = "0.1.0" +edition = "2021" + +[lib] +name = "bench" +path = "src/lib.rs" + +[[bin]] +name = "benchbin" +path = "src/bin.rs" + +[dependencies] +hex = { version = "0.4.3", features = ["serde"] } +eyre = "0.6.5" +prover = { path = "../prover" } +arbutil = { path = "../arbutil" } +clap = { version = "4.4.8", features = ["derive"] } +gperftools = { version = "0.2.0", optional = true } +serde = { version = "1.0.130", features = ["derive", "rc"] } +serde_json = "1.0.67" +serde_with = { version = "3.8.1", features = ["base64"] } + +[features] +counters = [] +cpuprof = ["gperftools"] +heapprof = ["gperftools", "gperftools/heap"] diff --git a/arbitrator/bench/src/bin.rs b/arbitrator/bench/src/bin.rs new file mode 100644 index 0000000000..f7e69f5373 --- /dev/null +++ b/arbitrator/bench/src/bin.rs @@ -0,0 +1,120 @@ +use std::{path::PathBuf, time::Duration}; + +use bench::prepare::*; +use clap::Parser; +use eyre::bail; + +#[cfg(feature = "cpuprof")] +use gperftools::profiler::PROFILER; + +#[cfg(feature = "heapprof")] +use gperftools::heap_profiler::HEAP_PROFILER; + +use prover::machine::MachineStatus; + +#[cfg(feature = "counters")] +use prover::{machine, memory, merkle}; + +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + /// Path to a preimages text file + #[arg(short, long)] + preimages_path: PathBuf, + + /// Path to a machine.wavm.br + #[arg(short, long)] + machine_path: PathBuf, +} + +fn main() -> eyre::Result<()> { + let args = Args::parse(); + let step_sizes = [1, 1 << 10, 1 << 15, 1 << 20, 1 << 24, 1 << 26, 1 << 28]; + + println!("Running benchmark with always merkleize feature on"); + for step_size in step_sizes { + let mut machine = prepare_machine(args.preimages_path.clone(), args.machine_path.clone())?; + let _ = machine.hash(); + let mut hash_times = vec![]; + let mut step_times = vec![]; + let mut num_iters = 0; + + #[cfg(feature = "cpuprof")] + PROFILER + .lock() + .unwrap() + .start(format!("./target/bench-{}.prof", step_size)) + .unwrap(); + + #[cfg(feature = "heapprof")] + HEAP_PROFILER + .lock() + .unwrap() + .start(format!("./target/bench-{}.hprof", step_size)) + .unwrap(); + + #[cfg(feature = "counters")] + { + machine::reset_counters(); + memory::reset_counters(); + merkle::reset_counters(); + } + let total = std::time::Instant::now(); + loop { + let start = std::time::Instant::now(); + machine.step_n(step_size)?; + let step_end_time = start.elapsed(); + step_times.push(step_end_time); + match machine.get_status() { + MachineStatus::Errored => { + println!("Errored"); + break; + } + MachineStatus::TooFar => { + bail!("Machine too far => position {}", machine.get_steps()) + } + MachineStatus::Running => {} + MachineStatus::Finished => { + break; + } + } + let start = std::time::Instant::now(); + let _ = machine.hash(); + let hash_end_time = start.elapsed(); + hash_times.push(hash_end_time); + num_iters += 1; + if num_iters == 200 { + break; + } + } + + #[cfg(feature = "cpuprof")] + PROFILER.lock().unwrap().stop().unwrap(); + + #[cfg(feature = "heapprof")] + HEAP_PROFILER.lock().unwrap().stop().unwrap(); + + let total_end_time = total.elapsed(); + println!( + "avg hash time {:>11?}, avg step time {:>12?}, step size {:>9}, num_iters {:>3}, total time {:>12?}", + average(&hash_times), + average(&step_times), + step_size, + num_iters, + total_end_time, + ); + #[cfg(feature = "counters")] + { + machine::print_counters(); + memory::print_counters(); + merkle::print_counters(); + } + } + Ok(()) +} + +fn average(numbers: &[Duration]) -> Duration { + let sum: Duration = numbers.iter().sum(); + let sum: u64 = sum.as_nanos().try_into().unwrap(); + Duration::from_nanos(sum / numbers.len() as u64) +} diff --git a/arbitrator/bench/src/lib.rs b/arbitrator/bench/src/lib.rs new file mode 100644 index 0000000000..5f7c024094 --- /dev/null +++ b/arbitrator/bench/src/lib.rs @@ -0,0 +1,2 @@ +pub mod parse_input; +pub mod prepare; diff --git a/arbitrator/bench/src/parse_input.rs b/arbitrator/bench/src/parse_input.rs new file mode 100644 index 0000000000..decc67372a --- /dev/null +++ b/arbitrator/bench/src/parse_input.rs @@ -0,0 +1,76 @@ +use arbutil::Bytes32; +use serde::{Deserialize, Serialize}; +use serde_json; +use serde_with::base64::Base64; +use serde_with::As; +use serde_with::DisplayFromStr; +use std::{ + collections::HashMap, + io::{self, BufRead}, +}; + +mod prefixed_hex { + use serde::{self, Deserialize, Deserializer, Serializer}; + + pub fn serialize(bytes: &Vec, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&format!("0x{}", hex::encode(bytes))) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + if let Some(s) = s.strip_prefix("0x") { + hex::decode(s).map_err(serde::de::Error::custom) + } else { + Err(serde::de::Error::custom("missing 0x prefix")) + } + } +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct PreimageMap(HashMap>); + +#[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(rename_all = "PascalCase")] +pub struct BatchInfo { + pub number: u64, + #[serde(with = "As::")] + pub data_b64: Vec, +} + +#[derive(Debug, Deserialize, Serialize)] +#[serde(rename_all = "PascalCase")] +pub struct StartState { + #[serde(with = "prefixed_hex")] + pub block_hash: Vec, + #[serde(with = "prefixed_hex")] + pub send_root: Vec, + pub batch: u64, + pub pos_in_batch: u64, +} + +#[derive(Debug, Deserialize, Serialize)] +#[serde(rename_all = "PascalCase")] +pub struct FileData { + pub id: u64, + pub has_delayed_msg: bool, + pub delayed_msg_nr: u64, + #[serde(with = "As::>>")] + pub preimages_b64: HashMap>>, + pub batch_info: Vec, + #[serde(with = "As::")] + pub delayed_msg_b64: Vec, + pub start_state: StartState, +} + +impl FileData { + pub fn from_reader(mut reader: R) -> io::Result { + let data = serde_json::from_reader(&mut reader)?; + Ok(data) + } +} diff --git a/arbitrator/bench/src/prepare.rs b/arbitrator/bench/src/prepare.rs new file mode 100644 index 0000000000..741a7350ac --- /dev/null +++ b/arbitrator/bench/src/prepare.rs @@ -0,0 +1,56 @@ +use arbutil::{Bytes32, PreimageType}; +use prover::machine::{argument_data_to_inbox, GlobalState, Machine}; +use prover::utils::CBytes; +use std::collections::HashMap; +use std::fs::File; +use std::io::BufReader; +use std::path::{Path, PathBuf}; +use std::sync::Arc; + +use crate::parse_input::*; + +pub fn prepare_machine(preimages: PathBuf, machines: PathBuf) -> eyre::Result { + let file = File::open(preimages)?; + let reader = BufReader::new(file); + + let data = FileData::from_reader(reader)?; + let preimages = data + .preimages_b64 + .into_iter() + .flat_map(|preimage| preimage.1.into_iter()) + .collect::>>(); + let preimage_resolver = move |_: u64, _: PreimageType, hash: Bytes32| -> Option { + preimages + .get(&hash) + .map(|data| CBytes::from(data.as_slice())) + }; + let preimage_resolver = Arc::new(Box::new(preimage_resolver)); + + let binary_path = Path::new(&machines); + let mut mach = Machine::new_from_wavm(binary_path)?; + + let block_hash: [u8; 32] = data.start_state.block_hash.try_into().unwrap(); + let block_hash: Bytes32 = block_hash.into(); + let send_root: [u8; 32] = data.start_state.send_root.try_into().unwrap(); + let send_root: Bytes32 = send_root.into(); + let bytes32_vals: [Bytes32; 2] = [block_hash, send_root]; + let u64_vals: [u64; 2] = [data.start_state.batch, data.start_state.pos_in_batch]; + let start_state = GlobalState { + bytes32_vals, + u64_vals, + }; + + mach.set_global_state(start_state); + + mach.set_preimage_resolver(preimage_resolver); + + let identifier = argument_data_to_inbox(0).unwrap(); + for batch_info in data.batch_info.iter() { + mach.add_inbox_msg(identifier, batch_info.number, batch_info.data_b64.clone()); + } + + let identifier = argument_data_to_inbox(1).unwrap(); + mach.add_inbox_msg(identifier, data.delayed_msg_nr, data.delayed_msg_b64); + + Ok(mach) +} diff --git a/arbitrator/prover/Cargo.toml b/arbitrator/prover/Cargo.toml index 0b42013808..5475647765 100644 --- a/arbitrator/prover/Cargo.toml +++ b/arbitrator/prover/Cargo.toml @@ -8,6 +8,7 @@ publish = false bincode = "1.3.3" derivative = "2.2.0" digest = "0.9.0" +bitvec = { version = "1", features = ["serde"] } eyre = "0.6.5" fnv = "1.0.7" hex = "0.4.3" @@ -40,6 +41,15 @@ c-kzg = { version = "0.4.0", optional = true } # TODO: look into switching to ru sha2 = "0.9.9" lru = "0.12.3" once_cell = "1.19.0" +enum-iterator = "2.0.1" + +[dev-dependencies] +criterion = { version = "0.5.0", features = ["html_reports"] } +rand = "0.8.4" + +[[bench]] +name = "merkle_bench" +harness = false [lib] name = "prover" @@ -47,6 +57,7 @@ crate-type = ["staticlib", "lib"] [features] default = ["native", "rayon", "singlepass_rayon"] +counters = [] native = ["dep:wasmer", "dep:wasmer-compiler-singlepass", "brotli/wasmer_traits", "dep:c-kzg"] singlepass_rayon = ["wasmer-compiler-singlepass?/rayon"] rayon = ["dep:rayon"] diff --git a/arbitrator/prover/benches/merkle_bench.rs b/arbitrator/prover/benches/merkle_bench.rs new file mode 100644 index 0000000000..98ac09a20e --- /dev/null +++ b/arbitrator/prover/benches/merkle_bench.rs @@ -0,0 +1,52 @@ +use arbutil::Bytes32; +use criterion::{criterion_group, criterion_main, Criterion}; +use prover::merkle::{Merkle, MerkleType}; +use rand::Rng; + +fn resize_and_set_leaves(merkle: Merkle, rng: &mut rand::rngs::ThreadRng) { + for _ in 0..100 { + merkle.resize(merkle.len() + 5).expect("resize failed"); + for _ in 0..(merkle.len() / 10) { + let random_index = rng.gen_range(0..merkle.len()); + merkle.set(random_index, Bytes32::from([rng.gen_range(0u8..9); 32])); + } + } + merkle.root(); +} + +fn merkle_benchmark(c: &mut Criterion) { + let mut rng = rand::thread_rng(); + let leaves = vec![ + Bytes32::from([1; 32]), + Bytes32::from([2; 32]), + Bytes32::from([3; 32]), + Bytes32::from([4; 32]), + Bytes32::from([5; 32]), + ]; + + // Perform many calls to set leaves to new values + c.bench_function("resize_set_leaves_and_root", |b| { + b.iter(|| { + let merkle = Merkle::new_advanced(MerkleType::Memory, leaves.clone(), 20); + resize_and_set_leaves(merkle.clone(), &mut rng); + }) + }); +} + +fn merkle_construction(c: &mut Criterion) { + let mut rng = rand::thread_rng(); + let mut leaves: Vec = Vec::with_capacity(1 << 20); + for _ in 0..(1 << 20) { + leaves.push(Bytes32::from([rng.gen_range(0u8..9); 32])); + } + + c.bench_function("merkle_construction", |b| { + b.iter(|| { + let merkle = Merkle::new_advanced(MerkleType::Memory, leaves.clone(), 21); + merkle.root(); + }) + }); +} + +criterion_group!(benches, merkle_benchmark, merkle_construction); +criterion_main!(benches); diff --git a/arbitrator/prover/src/lib.rs b/arbitrator/prover/src/lib.rs index c8649a4b3d..0f537478eb 100644 --- a/arbitrator/prover/src/lib.rs +++ b/arbitrator/prover/src/lib.rs @@ -9,8 +9,8 @@ mod host; mod kzg; pub mod machine; /// cbindgen:ignore -mod memory; -mod merkle; +pub mod memory; +pub mod merkle; mod print; pub mod programs; mod reinterpret; @@ -101,8 +101,7 @@ unsafe fn arbitrator_load_machine_impl( &libraries, binary_path, true, - false, - false, + true, debug_chain, debug_chain, Default::default(), diff --git a/arbitrator/prover/src/machine.rs b/arbitrator/prover/src/machine.rs index 5466c7f790..c7550e642a 100644 --- a/arbitrator/prover/src/machine.rs +++ b/arbitrator/prover/src/machine.rs @@ -32,6 +32,10 @@ use serde::{Deserialize, Serialize}; use serde_with::serde_as; use sha3::Keccak256; use smallvec::SmallVec; + +#[cfg(feature = "counters")] +use std::sync::atomic::{AtomicUsize, Ordering}; + use std::{ borrow::Cow, convert::{TryFrom, TryInto}, @@ -44,12 +48,29 @@ use std::{ path::{Path, PathBuf}, sync::Arc, }; + use wasmer_types::FunctionIndex; use wasmparser::{DataKind, ElementItems, ElementKind, Operator, RefType, TableType}; #[cfg(feature = "rayon")] use rayon::prelude::*; +#[cfg(feature = "counters")] +static GET_MODULES_MERKLE_COUNTER: AtomicUsize = AtomicUsize::new(0); + +#[cfg(feature = "counters")] +pub fn print_counters() { + println!( + "GET_MODULES_MERKLE_COUNTER: {}", + GET_MODULES_MERKLE_COUNTER.load(Ordering::Relaxed) + ); +} + +#[cfg(feature = "counters")] +pub fn reset_counters() { + GET_MODULES_MERKLE_COUNTER.store(0, Ordering::Relaxed); +} + fn hash_call_indirect_data(table: u32, ty: &FunctionType) -> Bytes32 { let mut h = Keccak256::new(); h.update("Call indirect:"); @@ -1200,7 +1221,6 @@ impl Machine { library_paths: &[PathBuf], binary_path: &Path, language_support: bool, - always_merkleize: bool, allow_hostapi_from_main: bool, debug_funcs: bool, debug_info: bool, @@ -1225,7 +1245,6 @@ impl Machine { &libraries, bin, language_support, - always_merkleize, allow_hostapi_from_main, debug_funcs, debug_info, @@ -1255,8 +1274,7 @@ impl Machine { &[soft_float, wasi_stub, user_test], bin, false, - false, - false, + true, compile.debug.debug_funcs, true, GlobalState::default(), @@ -1303,7 +1321,6 @@ impl Machine { libraries: &[WasmBinary<'_>], bin: WasmBinary<'_>, runtime_support: bool, - always_merkleize: bool, allow_hostapi_from_main: bool, debug_funcs: bool, debug_info: bool, @@ -1506,18 +1523,12 @@ impl Machine { let tables_hashes: Result<_, _> = module.tables.iter().map(Table::hash).collect(); module.tables_merkle = Merkle::new(MerkleType::Table, tables_hashes?); - - if always_merkleize { - module.memory.cache_merkle_tree(); - } - } - let mut modules_merkle = None; - if always_merkleize { - modules_merkle = Some(Merkle::new( - MerkleType::Module, - modules.iter().map(Module::hash).collect(), - )); + module.memory.cache_merkle_tree(); } + let modules_merkle = Some(Merkle::new( + MerkleType::Module, + modules.iter().map(Module::hash).collect(), + )); // find the first inbox index that's out of bounds let first_too_far = inbox_contents @@ -1577,7 +1588,12 @@ impl Machine { MerkleType::Function, module.funcs.iter().map(Function::hash).collect(), )); + module.memory.cache_merkle_tree(); } + let modules_merkle = Some(Merkle::new( + MerkleType::Module, + modules.iter().map(Module::hash).collect(), + )); let mut mach = Machine { status: MachineStatus::Running, thread_state: ThreadState::Main, @@ -1586,7 +1602,7 @@ impl Machine { internal_stack: Vec::new(), frame_stacks: vec![Vec::new()], modules, - modules_merkle: None, + modules_merkle, global_state: Default::default(), pc: ProgramCounter::default(), stdio_output: Vec::new(), @@ -1906,20 +1922,11 @@ impl Machine { func = &module.funcs[self.pc.func()]; }; } - macro_rules! flush_module { - () => { - if let Some(merkle) = self.modules_merkle.as_mut() { - merkle.set(self.pc.module(), module.hash()); - } - }; - } macro_rules! error { () => { error!("") }; ($format:expr $(, $message:expr)*) => {{ - flush_module!(); - if self.debug_info { println!("\n{} {}", "error on line".grey(), line!().pink()); println!($format, $($message.pink()),*); @@ -1938,7 +1945,6 @@ impl Machine { continue; } self.status = MachineStatus::Errored; - module = &mut self.modules[self.pc.module()]; break; }}; } @@ -1949,7 +1955,6 @@ impl Machine { println!("\n{}", "Machine out of steps".red()); self.status = MachineStatus::Errored; self.print_backtrace(true); - module = &mut self.modules[self.pc.module()]; break; } @@ -2009,9 +2014,6 @@ impl Machine { Value::RefNull => error!(), Value::InternalRef(pc) => { let changing_module = pc.module != self.pc.module; - if changing_module { - flush_module!(); - } self.pc = pc; if changing_module { module = &mut self.modules[self.pc.module()]; @@ -2031,7 +2033,6 @@ impl Machine { func = &module.funcs[self.pc.func()]; } Opcode::CrossModuleCall => { - flush_module!(); value_stack.push(Value::InternalRef(self.pc)); value_stack.push(self.pc.module.into()); value_stack.push(module.internals_offset.into()); @@ -2042,7 +2043,6 @@ impl Machine { reset_refs!(); } Opcode::CrossModuleForward => { - flush_module!(); let frame = frame_stack.last().unwrap(); value_stack.push(Value::InternalRef(self.pc)); value_stack.push(frame.caller_module.into()); @@ -2054,7 +2054,6 @@ impl Machine { reset_refs!(); } Opcode::CrossModuleInternalCall => { - flush_module!(); let call_internal = inst.argument_data as u32; let call_module = value_stack.pop().unwrap().assume_u32(); value_stack.push(Value::InternalRef(self.pc)); @@ -2077,7 +2076,6 @@ impl Machine { .ok() .and_then(|o| current_frame.caller_module_internals.checked_add(o)) .expect("Internal call function index overflow"); - flush_module!(); self.pc.module = current_frame.caller_module; self.pc.func = func_idx; self.pc.inst = 0; @@ -2509,7 +2507,6 @@ impl Machine { let dots = (modules.len() > 16).then_some("...").unwrap_or_default(); bail!("no program for {hash} in {{{}{dots}}}", keys.join(", ")) }; - flush_module!(); // put the new module's offset on the stack let index = self.modules.len() as u32; @@ -2522,7 +2519,6 @@ impl Machine { reset_refs!(); } Opcode::UnlinkModule => { - flush_module!(); self.modules.pop(); if let Some(cached) = &mut self.modules_merkle { cached.pop_leaf(); @@ -2562,7 +2558,6 @@ impl Machine { } } } - flush_module!(); if self.is_halted() && !self.stdio_output.is_empty() { // If we halted, print out any trailing output that didn't have a newline. Self::say(String::from_utf8_lossy(&self.stdio_output)); @@ -2686,7 +2681,13 @@ impl Machine { } fn get_modules_merkle(&self) -> Cow { + #[cfg(feature = "counters")] + GET_MODULES_MERKLE_COUNTER.fetch_add(1, Ordering::Relaxed); + if let Some(merkle) = &self.modules_merkle { + for (i, module) in self.modules.iter().enumerate() { + merkle.set(i, module.hash()); + } Cow::Borrowed(merkle) } else { Cow::Owned(Merkle::new( diff --git a/arbitrator/prover/src/main.rs b/arbitrator/prover/src/main.rs index e10a415389..dba32e0e72 100644 --- a/arbitrator/prover/src/main.rs +++ b/arbitrator/prover/src/main.rs @@ -35,8 +35,6 @@ struct Opts { #[structopt(long)] inbox_add_stub_headers: bool, #[structopt(long)] - always_merkleize: bool, - #[structopt(long)] debug_funcs: bool, #[structopt(long)] /// print modules to the console @@ -207,7 +205,6 @@ fn main() -> Result<()> { &opts.libraries, &opts.binary, true, - opts.always_merkleize, opts.allow_hostapi, opts.debug_funcs, true, diff --git a/arbitrator/prover/src/memory.rs b/arbitrator/prover/src/memory.rs index bd96221091..5853dc87e1 100644 --- a/arbitrator/prover/src/memory.rs +++ b/arbitrator/prover/src/memory.rs @@ -8,14 +8,35 @@ use crate::{ use arbutil::Bytes32; use digest::Digest; use eyre::{bail, ErrReport, Result}; +use parking_lot::Mutex; use serde::{Deserialize, Serialize}; use sha3::Keccak256; -use std::{borrow::Cow, convert::TryFrom}; +use std::{borrow::Cow, collections::HashSet, convert::TryFrom}; + +#[cfg(feature = "counters")] +use std::sync::atomic::{AtomicUsize, Ordering}; + use wasmer_types::Pages; #[cfg(feature = "rayon")] use rayon::prelude::*; +#[cfg(feature = "counters")] +static MEM_HASH_COUNTER: AtomicUsize = AtomicUsize::new(0); + +#[cfg(feature = "counters")] +pub fn reset_counters() { + MEM_HASH_COUNTER.store(0, Ordering::Relaxed); +} + +#[cfg(feature = "counters")] +pub fn print_counters() { + println!( + "Memory hash count: {}", + MEM_HASH_COUNTER.load(Ordering::Relaxed) + ); +} + pub struct MemoryType { pub min: Pages, pub max: Option, @@ -44,12 +65,14 @@ impl TryFrom<&wasmparser::MemoryType> for MemoryType { } } -#[derive(PartialEq, Eq, Clone, Debug, Default, Serialize, Deserialize)] +#[derive(Debug, Default, Serialize, Deserialize)] pub struct Memory { buffer: Vec, #[serde(skip)] pub merkle: Option, pub max_size: u64, + #[serde(skip)] + dirty_leaves: Mutex>, } fn hash_leaf(bytes: [u8; Memory::LEAF_SIZE]) -> Bytes32 { @@ -78,6 +101,17 @@ fn div_round_up(num: usize, denom: usize) -> usize { res } +impl Clone for Memory { + fn clone(&self) -> Self { + Memory { + buffer: self.buffer.clone(), + merkle: self.merkle.clone(), + max_size: self.max_size, + dirty_leaves: Mutex::new(self.dirty_leaves.lock().clone()), + } + } +} + impl Memory { pub const LEAF_SIZE: usize = 32; /// Only used when initializing a memory to determine its size @@ -91,6 +125,7 @@ impl Memory { buffer: vec![0u8; size], merkle: None, max_size, + dirty_leaves: Mutex::new(HashSet::new()), } } @@ -100,6 +135,10 @@ impl Memory { pub fn merkelize(&self) -> Cow<'_, Merkle> { if let Some(m) = &self.merkle { + let mut dirt = self.dirty_leaves.lock(); + for leaf_idx in dirt.drain() { + m.set(leaf_idx, hash_leaf(self.get_leaf_data(leaf_idx))); + } return Cow::Borrowed(m); } // Round the size up to 8 byte long leaves, then round up to the next power of two number of leaves @@ -111,23 +150,22 @@ impl Memory { #[cfg(not(feature = "rayon"))] let leaf_hashes = self.buffer.chunks(Self::LEAF_SIZE); - let mut leaf_hashes: Vec = leaf_hashes + let leaf_hashes: Vec = leaf_hashes .map(|leaf| { let mut full_leaf = [0u8; 32]; full_leaf[..leaf.len()].copy_from_slice(leaf); hash_leaf(full_leaf) }) .collect(); - if leaf_hashes.len() < leaves { - let empty_hash = hash_leaf([0u8; 32]); - leaf_hashes.resize(leaves, empty_hash); + let size = leaf_hashes.len(); + let m = Merkle::new_advanced(MerkleType::Memory, leaf_hashes, Self::MEMORY_LAYERS); + if size < leaves { + m.resize(leaves).unwrap_or_else(|_| { + panic!("Couldn't resize merkle tree from {} to {}", size, leaves) + }); } - Cow::Owned(Merkle::new_advanced( - MerkleType::Memory, - leaf_hashes, - hash_leaf([0u8; 32]), - Self::MEMORY_LAYERS, - )) + self.dirty_leaves.lock().clear(); + Cow::Owned(m) } pub fn get_leaf_data(&self, leaf_idx: usize) -> [u8; Self::LEAF_SIZE] { @@ -142,6 +180,8 @@ impl Memory { } pub fn hash(&self) -> Bytes32 { + #[cfg(feature = "counters")] + MEM_HASH_COUNTER.fetch_add(1, Ordering::Relaxed); let mut h = Keccak256::new(); h.update("Memory:"); h.update((self.buffer.len() as u64).to_be_bytes()); @@ -222,7 +262,11 @@ impl Memory { } #[must_use] + /// Stores a value in memory, returns false if the value would overflow the buffer. + /// + /// bytes is the number of bytes to store. It must be <= 8. pub fn store_value(&mut self, idx: u64, value: u64, bytes: u8) -> bool { + assert!(bytes <= 8); let Some(end_idx) = idx.checked_add(bytes.into()) else { return false; }; @@ -233,22 +277,19 @@ impl Memory { let end_idx = end_idx as usize; let buf = value.to_le_bytes(); self.buffer[idx..end_idx].copy_from_slice(&buf[..bytes.into()]); - - if let Some(mut merkle) = self.merkle.take() { - let start_leaf = idx / Self::LEAF_SIZE; - merkle.set(start_leaf, hash_leaf(self.get_leaf_data(start_leaf))); - let end_leaf = (end_idx - 1) / Self::LEAF_SIZE; - if end_leaf != start_leaf { - merkle.set(end_leaf, hash_leaf(self.get_leaf_data(end_leaf))); - } - self.merkle = Some(merkle); - } + let mut dirty_leaves = self.dirty_leaves.lock(); + dirty_leaves.insert(idx / Self::LEAF_SIZE); + dirty_leaves.insert((end_idx - 1) / Self::LEAF_SIZE); true } #[must_use] + /// Stores a slice in memory, returns false if the value would overflow the buffer. + /// + /// The length of value <= 32. pub fn store_slice_aligned(&mut self, idx: u64, value: &[u8]) -> bool { + assert!(value.len() <= Self::LEAF_SIZE); if idx % Self::LEAF_SIZE as u64 != 0 { return false; } @@ -261,13 +302,7 @@ impl Memory { let idx = idx as usize; let end_idx = end_idx as usize; self.buffer[idx..end_idx].copy_from_slice(value); - - if let Some(mut merkle) = self.merkle.take() { - let start_leaf = idx / Self::LEAF_SIZE; - merkle.set(start_leaf, hash_leaf(self.get_leaf_data(start_leaf))); - // No need for second merkle - assert!(value.len() <= Self::LEAF_SIZE); - } + self.dirty_leaves.lock().insert(idx / Self::LEAF_SIZE); true } @@ -288,7 +323,7 @@ impl Memory { } pub fn get_range(&self, offset: usize, len: usize) -> Option<&[u8]> { - let end = offset.checked_add(len)?; + let end: usize = offset.checked_add(len)?; if end > self.buffer.len() { return None; } @@ -309,18 +344,61 @@ impl Memory { } pub fn resize(&mut self, new_size: usize) { - let had_merkle_tree = self.merkle.is_some(); - self.merkle = None; self.buffer.resize(new_size, 0); - if had_merkle_tree { - self.cache_merkle_tree(); + if let Some(merkle) = &mut self.merkle { + merkle + .resize(new_size / Self::LEAF_SIZE) + .unwrap_or_else(|_| { + panic!( + "Couldn't resize merkle tree from {} to {}", + merkle.len(), + new_size + ) + }); } } } +pub mod testing { + use arbutil::Bytes32; + + pub fn empty_leaf_hash() -> Bytes32 { + let leaf = [0u8; 32]; + super::hash_leaf(leaf) + } +} + #[cfg(test)] mod test { + use arbutil::Bytes32; + use crate::memory::round_up_to_power_of_two; + use crate::memory::testing; + + use super::Memory; + + #[test] + pub fn fixed_memory_hash() { + let module_memory_hash = Bytes32::from([ + 86u8, 177, 192, 60, 217, 123, 221, 153, 118, 79, 229, 122, 210, 48, 187, 104, 40, 84, + 112, 63, 137, 86, 54, 2, 56, 118, 72, 158, 242, 225, 65, 80, + ]); + let memory = Memory::new(65536, 1); + assert_eq!(memory.hash(), module_memory_hash); + } + + #[test] + pub fn empty_leaf_hash() { + let hash = testing::empty_leaf_hash(); + print!("Bytes32(["); + for i in 0..32 { + print!("{}", hash[i]); + if i < 31 { + print!(", "); + } + } + print!("]);"); + } #[test] pub fn test_round_up_power_of_two() { diff --git a/arbitrator/prover/src/merkle.rs b/arbitrator/prover/src/merkle.rs index 16306bd611..98ba6591f0 100644 --- a/arbitrator/prover/src/merkle.rs +++ b/arbitrator/prover/src/merkle.rs @@ -2,15 +2,47 @@ // For license information, see https://github.com/nitro/blob/master/LICENSE use arbutil::Bytes32; +use bitvec::prelude::*; +use core::panic; use digest::Digest; +use enum_iterator::Sequence; +use parking_lot::Mutex; use serde::{Deserialize, Serialize}; use sha3::Keccak256; -use std::convert::TryFrom; +use std::cmp::max; +use std::convert::{TryFrom, TryInto}; #[cfg(feature = "rayon")] use rayon::prelude::*; -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +mod zerohashes; +use self::zerohashes::{EMPTY_HASH, ZERO_HASHES}; +#[cfg(feature = "counters")] +use { + enum_iterator::all, + lazy_static::lazy_static, + std::collections::HashMap, + std::sync::atomic::{AtomicUsize, Ordering}, +}; + +#[cfg(feature = "counters")] +fn create_counters_hashmap() -> HashMap { + let mut map = HashMap::new(); + for ty in all::() { + map.insert(ty, AtomicUsize::new(0)); + } + map +} + +#[cfg(feature = "counters")] +lazy_static! { + static ref NEW_COUNTERS: HashMap = create_counters_hashmap(); + static ref ROOT_COUNTERS: HashMap = create_counters_hashmap(); + static ref SET_COUNTERS: HashMap = create_counters_hashmap(); + static ref RESIZE_COUNTERS: HashMap = create_counters_hashmap(); +} + +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize, Sequence)] pub enum MerkleType { Empty, Value, @@ -28,6 +60,36 @@ impl Default for MerkleType { } } +#[cfg(feature = "counters")] +pub fn print_counters() { + for ty in all::() { + if ty == MerkleType::Empty { + continue; + } + println!( + "{} New: {}, Root: {}, Set: {} Resize: {}", + ty.get_prefix(), + NEW_COUNTERS[&ty].load(Ordering::Relaxed), + ROOT_COUNTERS[&ty].load(Ordering::Relaxed), + SET_COUNTERS[&ty].load(Ordering::Relaxed), + RESIZE_COUNTERS[&ty].load(Ordering::Relaxed), + ); + } +} + +#[cfg(feature = "counters")] +pub fn reset_counters() { + for ty in all::() { + if ty == MerkleType::Empty { + continue; + } + NEW_COUNTERS[&ty].store(0, Ordering::Relaxed); + ROOT_COUNTERS[&ty].store(0, Ordering::Relaxed); + SET_COUNTERS[&ty].store(0, Ordering::Relaxed); + RESIZE_COUNTERS[&ty].store(0, Ordering::Relaxed); + } +} + impl MerkleType { pub fn get_prefix(self) -> &'static str { match self { @@ -43,15 +105,36 @@ impl MerkleType { } } -#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +struct Layers { + data: Vec>, + dirty_leaf_parents: BitVec, +} + +/// A Merkle tree with a fixed number of layers +/// +/// https://en.wikipedia.org/wiki/Merkle_tree +/// +/// Each instance's leaves contain the hashes of a specific [MerkleType]. +/// The tree does not grow in height, but it can be initialized with fewer +/// leaves than the number that could be contained in its layers. +/// +/// When initialized with [Merkle::new], the tree has the minimum depth +/// necessary to hold all the leaves. (e.g. 5 leaves -> 4 layers.) +/// +/// It can be over-provisioned using the [Merkle::new_advanced] method +/// and passing a minimum depth. +/// +/// This structure does not contain the data itself, only the hashes. +#[derive(Debug, Default, Serialize, Deserialize)] pub struct Merkle { ty: MerkleType, - layers: Vec>, - empty_layers: Vec, + #[serde(with = "mutex_sedre")] + layers: Mutex, min_depth: usize, } -fn hash_node(ty: MerkleType, a: Bytes32, b: Bytes32) -> Bytes32 { +fn hash_node(ty: MerkleType, a: impl AsRef<[u8]>, b: impl AsRef<[u8]>) -> Bytes32 { let mut h = Keccak256::new(); h.update(ty.get_prefix()); h.update(a); @@ -59,47 +142,131 @@ fn hash_node(ty: MerkleType, a: Bytes32, b: Bytes32) -> Bytes32 { h.finalize().into() } +const fn empty_hash_at(ty: MerkleType, layer_i: usize) -> &'static Bytes32 { + match ty { + MerkleType::Empty => EMPTY_HASH, + MerkleType::Value => &ZERO_HASHES[0][layer_i], + MerkleType::Function => &ZERO_HASHES[1][layer_i], + MerkleType::Instruction => &ZERO_HASHES[2][layer_i], + MerkleType::Memory => &ZERO_HASHES[3][layer_i], + MerkleType::Table => &ZERO_HASHES[4][layer_i], + MerkleType::TableElement => &ZERO_HASHES[5][layer_i], + MerkleType::Module => &ZERO_HASHES[6][layer_i], + } +} + +#[inline] +#[cfg(feature = "rayon")] +fn new_layer(ty: MerkleType, layer: &[Bytes32], empty_hash: &'static Bytes32) -> Vec { + let mut new_layer: Vec = Vec::with_capacity(layer.len() >> 1); + let chunks = layer.par_chunks(2); + chunks + .map(|chunk| hash_node(ty, chunk[0], chunk.get(1).unwrap_or(empty_hash))) + .collect_into_vec(&mut new_layer); + new_layer +} + +#[inline] +#[cfg(not(feature = "rayon"))] +fn new_layer(ty: MerkleType, layer: &[Bytes32], empty_hash: &'static Bytes32) -> Vec { + let new_layer = layer + .chunks(2) + .map(|chunk| hash_node(ty, chunk[0], chunk.get(1).unwrap_or(empty_hash))) + .collect(); + new_layer +} + +impl Clone for Merkle { + fn clone(&self) -> Self { + let leaves = self.layers.lock().data.first().cloned().unwrap_or_default(); + Merkle::new_advanced(self.ty, leaves, self.min_depth) + } +} + impl Merkle { + /// Creates a new Merkle tree with the given type and leaf hashes. + /// The tree is built up to the minimum depth necessary to hold all the + /// leaves. pub fn new(ty: MerkleType, hashes: Vec) -> Merkle { - Self::new_advanced(ty, hashes, Bytes32::default(), 0) + Self::new_advanced(ty, hashes, 0) } - pub fn new_advanced( - ty: MerkleType, - hashes: Vec, - empty_hash: Bytes32, - min_depth: usize, - ) -> Merkle { - if hashes.is_empty() { + /// Creates a new Merkle tree with the given type, leaf hashes, a hash to + /// use for representing empty leaves, and a minimum depth. + pub fn new_advanced(ty: MerkleType, hashes: Vec, min_depth: usize) -> Merkle { + #[cfg(feature = "counters")] + NEW_COUNTERS[&ty].fetch_add(1, Ordering::Relaxed); + if hashes.is_empty() && min_depth == 0 { return Merkle::default(); } - let mut layers = vec![hashes]; - let mut empty_layers = vec![empty_hash]; + let depth = if hashes.len() > 1 { + min_depth.max(((hashes.len() - 1).ilog2() + 1).try_into().unwrap()) + } else { + min_depth + }; + let mut layers: Vec> = Vec::with_capacity(depth); + let dirty_leaf_parents = bitvec![0; (hashes.len() + 1) >> 1]; + layers.push(hashes); while layers.last().unwrap().len() > 1 || layers.len() < min_depth { - let empty_layer = *empty_layers.last().unwrap(); - - #[cfg(feature = "rayon")] - let new_layer = layers.last().unwrap().par_chunks(2); - - #[cfg(not(feature = "rayon"))] - let new_layer = layers.last().unwrap().chunks(2); + let layer = layers.last().unwrap(); + let empty_hash = empty_hash_at(ty, layers.len() - 1); - let new_layer = new_layer - .map(|chunk| hash_node(ty, chunk[0], chunk.get(1).cloned().unwrap_or(empty_layer))) - .collect(); - empty_layers.push(hash_node(ty, empty_layer, empty_layer)); + let new_layer = new_layer(ty, layer, empty_hash); layers.push(new_layer); } + let layers = Mutex::new(Layers { + data: layers, + dirty_leaf_parents, + }); Merkle { ty, layers, - empty_layers, min_depth, } } + fn rehash(&self, layers: &mut Layers) { + // If nothing is dirty, then there's no need to rehash. + if layers.dirty_leaf_parents.is_empty() { + return; + } + let mut dirt = layers.dirty_leaf_parents.clone(); + // Process dirty indices starting from layer 1 (layer 0 is the leaves). + for layer_i in 1..layers.data.len() { + let mut new_dirt = bitvec![0; (dirt.len() + 1) >> 1]; + for idx in dirt.iter_ones() { + let left_child_idx = idx << 1; + let right_child_idx = left_child_idx + 1; + // The left child is guaranteed to exist, but the right one + // might not if the number of child nodes is odd. + let left = layers.data[layer_i - 1][left_child_idx]; + let right = layers.data[layer_i - 1] + .get(right_child_idx) + .unwrap_or(empty_hash_at(self.ty, layer_i - 1)); + let new_hash = hash_node(self.ty, left, right); + if idx < layers.data[layer_i].len() { + layers.data[layer_i][idx] = new_hash; + } else { + // Push the new parent hash onto the end of the layer. + assert_eq!(idx, layers.data[layer_i].len()); + layers.data[layer_i].push(new_hash); + } + // Mark the node's parent as dirty unless it's the root. + if layer_i < layers.data.len() - 1 { + new_dirt.set(idx >> 1, true); + } + } + dirt = new_dirt; + } + layers.dirty_leaf_parents.fill(false); + } + pub fn root(&self) -> Bytes32 { - if let Some(layer) = self.layers.last() { + #[cfg(feature = "counters")] + ROOT_COUNTERS[&self.ty].fetch_add(1, Ordering::Relaxed); + let mut layers = self.layers.lock(); + self.rehash(&mut layers); + if let Some(layer) = layers.data.last() { assert_eq!(layer.len(), 1); layer[0] } else { @@ -107,18 +274,33 @@ impl Merkle { } } - pub fn leaves(&self) -> &[Bytes32] { - if self.layers.is_empty() { - &[] - } else { - &self.layers[0] + // Returns the total number of leaves the tree can hold. + #[inline] + fn capacity(&self) -> usize { + let layers = self.layers.lock(); + if layers.data.is_empty() { + return 0; } + 1 << (layers.data.len() - 1) + } + + // Returns the number of leaves in the tree. + pub fn len(&self) -> usize { + self.layers.lock().data[0].len() + } + + pub fn is_empty(&self) -> bool { + let layers = self.layers.lock(); + layers.data.is_empty() || layers.data[0].is_empty() } #[must_use] pub fn prove(&self, idx: usize) -> Option> { - if idx >= self.leaves().len() { - return None; + { + let layers = self.layers.lock(); + if layers.data.is_empty() || idx >= layers.data[0].len() { + return None; + } } Some(self.prove_any(idx)) } @@ -126,9 +308,11 @@ impl Merkle { /// creates a merkle proof regardless of if the leaf has content #[must_use] pub fn prove_any(&self, mut idx: usize) -> Vec { - let mut proof = vec![u8::try_from(self.layers.len() - 1).unwrap()]; - for (layer_i, layer) in self.layers.iter().enumerate() { - if layer_i == self.layers.len() - 1 { + let mut layers = self.layers.lock(); + self.rehash(&mut layers); + let mut proof = vec![u8::try_from(layers.data.len() - 1).unwrap()]; + for (layer_i, layer) in layers.data.iter().enumerate() { + if layer_i == layers.data.len() - 1 { break; } let counterpart = idx ^ 1; @@ -136,7 +320,7 @@ impl Merkle { layer .get(counterpart) .cloned() - .unwrap_or_else(|| self.empty_layers[layer_i]), + .unwrap_or_else(|| *empty_hash_at(self.ty, layer_i)), ); idx >>= 1; } @@ -146,44 +330,271 @@ impl Merkle { /// Adds a new leaf to the merkle /// Currently O(n) in the number of leaves (could be log(n)) pub fn push_leaf(&mut self, leaf: Bytes32) { - let mut leaves = self.layers.swap_remove(0); + let mut leaves = self.layers.lock().data.swap_remove(0); leaves.push(leaf); - let empty = self.empty_layers[0]; - *self = Self::new_advanced(self.ty, leaves, empty, self.min_depth); + *self = Self::new_advanced(self.ty, leaves, self.min_depth); } /// Removes the rightmost leaf from the merkle /// Currently O(n) in the number of leaves (could be log(n)) pub fn pop_leaf(&mut self) { - let mut leaves = self.layers.swap_remove(0); + let mut leaves = self.layers.lock().data.swap_remove(0); leaves.pop(); - let empty = self.empty_layers[0]; - *self = Self::new_advanced(self.ty, leaves, empty, self.min_depth); + *self = Self::new_advanced(self.ty, leaves, self.min_depth); } - pub fn set(&mut self, mut idx: usize, hash: Bytes32) { - if self.layers[0][idx] == hash { + // Sets the leaf at the given index to the given hash. + // Panics if the index is out of bounds (since the structure doesn't grow). + pub fn set(&self, idx: usize, hash: Bytes32) { + #[cfg(feature = "counters")] + SET_COUNTERS[&self.ty].fetch_add(1, Ordering::Relaxed); + let mut layers = self.layers.lock(); + if layers.data[0][idx] == hash { return; } - let mut next_hash = hash; - let empty_layers = &self.empty_layers; - let layers_len = self.layers.len(); - for (layer_i, layer) in self.layers.iter_mut().enumerate() { - layer[idx] = next_hash; - if layer_i == layers_len - 1 { - // next_hash isn't needed - break; + layers.data[0][idx] = hash; + layers.dirty_leaf_parents.set(idx >> 1, true); + } + + /// Resizes the number of leaves the tree can hold. + /// + /// The extra space is filled with empty hashes. + pub fn resize(&self, new_len: usize) -> Result { + #[cfg(feature = "counters")] + RESIZE_COUNTERS[&self.ty].fetch_add(1, Ordering::Relaxed); + if new_len > self.capacity() { + return Err( + "Cannot resize to a length greater than the capacity of the tree.".to_owned(), + ); + } + let mut layers = self.layers.lock(); + let start = layers.data[0].len(); + let mut layer_size = new_len; + for (layer_i, layer) in layers.data.iter_mut().enumerate() { + layer.resize(layer_size, *empty_hash_at(self.ty, layer_i)); + layer_size = max(layer_size >> 1, 1); + } + // This will set one or no values depending on if the length was even or odd. + layers.dirty_leaf_parents[(start >> 1)..].fill(true); + // This then resizes and marks the dirty leaf parents as dirty. + layers.dirty_leaf_parents.resize(new_len >> 1, true); + Ok(layers.data[0].len()) + } +} + +impl PartialEq for Merkle { + // There are only three members of a Merkle, the type, the layers, and the min_depth. + // + // It should be obvious that only if the type and layers are equal, will the root hash + // be equal. So, it is sufficient to compare the root hash when checking equality. + // + // However, it is possible that the min_depth may differ between two merkle trees which + // have the same type and layers. The root hash will still be equal unless the min_depth + // is larger than the depth required to hold the data in the layers. + // + // For example, a Merkle tree with 5 leaves requires 3 layeers to hold the data. If the + // min_depth is 1 on one tree and 2 on another, the root has would still be equal + // because the same nodes are hashed together. However, the min_dpeth was 4, then, + // there would be 4 layers in that tree, and the root hash would be different. + fn eq(&self, other: &Self) -> bool { + self.root() == other.root() && self.ty == other.ty + } +} + +impl Eq for Merkle {} + +pub mod mutex_sedre { + use parking_lot::Mutex; + + pub fn serialize(data: &Mutex, serializer: S) -> Result + where + S: serde::Serializer, + T: serde::Serialize, + { + data.lock().serialize(serializer) + } + + pub fn deserialize<'de, D, T>(deserializer: D) -> Result, D::Error> + where + D: serde::Deserializer<'de>, + T: serde::Deserialize<'de>, + { + Ok(Mutex::new(T::deserialize(deserializer)?)) + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::memory; + use arbutil::Bytes32; + use core::panic; + use enum_iterator::all; + + #[test] + fn resize_works() { + let hashes = vec![ + Bytes32::from([1; 32]), + Bytes32::from([2; 32]), + Bytes32::from([3; 32]), + Bytes32::from([4; 32]), + Bytes32::from([5; 32]), + ]; + let mut expected = hash_node( + MerkleType::Value, + hash_node( + MerkleType::Value, + hash_node( + MerkleType::Value, + Bytes32::from([1; 32]), + Bytes32::from([2; 32]), + ), + hash_node( + MerkleType::Value, + Bytes32::from([3; 32]), + Bytes32::from([4; 32]), + ), + ), + hash_node( + MerkleType::Value, + hash_node( + MerkleType::Value, + Bytes32::from([5; 32]), + Bytes32::from([0; 32]), + ), + hash_node( + MerkleType::Value, + Bytes32::from([0; 32]), + Bytes32::from([0; 32]), + ), + ), + ); + let merkle = Merkle::new(MerkleType::Value, hashes.clone()); + assert_eq!(merkle.capacity(), 8); + assert_eq!(merkle.root(), expected); + + let new_size = match merkle.resize(6) { + Ok(size) => size, + Err(e) => panic!("{}", e), + }; + assert_eq!(new_size, 6); + assert_eq!(merkle.root(), expected); + + merkle.set(5, Bytes32::from([6; 32])); + expected = hash_node( + MerkleType::Value, + hash_node( + MerkleType::Value, + hash_node( + MerkleType::Value, + Bytes32::from([1; 32]), + Bytes32::from([2; 32]), + ), + hash_node( + MerkleType::Value, + Bytes32::from([3; 32]), + Bytes32::from([4; 32]), + ), + ), + hash_node( + MerkleType::Value, + hash_node( + MerkleType::Value, + Bytes32::from([5; 32]), + Bytes32::from([6; 32]), + ), + hash_node( + MerkleType::Value, + Bytes32::from([0; 32]), + Bytes32::from([0; 32]), + ), + ), + ); + assert_eq!(merkle.root(), expected); + } + + #[test] + fn correct_capacity() { + let merkle: Merkle = Merkle::new(MerkleType::Value, vec![]); + assert_eq!(merkle.capacity(), 0); + let merkle = Merkle::new(MerkleType::Value, vec![Bytes32::from([1; 32])]); + assert_eq!(merkle.capacity(), 1); + let merkle = Merkle::new( + MerkleType::Value, + vec![Bytes32::from([1; 32]), Bytes32::from([2; 32])], + ); + assert_eq!(merkle.capacity(), 2); + let merkle = Merkle::new_advanced(MerkleType::Memory, vec![Bytes32::from([1; 32])], 11); + assert_eq!(merkle.capacity(), 1024); + } + + #[test] + #[ignore = "This is just used for generating the zero hashes for the memory merkle trees."] + fn emit_memory_zerohashes() { + // The following code was generated from the empty_leaf_hash() test in the memory package. + let mut empty_node = Bytes32([ + 57, 29, 211, 154, 252, 227, 18, 99, 65, 126, 203, 166, 252, 232, 32, 3, 98, 194, 254, + 186, 118, 14, 139, 192, 101, 156, 55, 194, 101, 11, 11, 168, + ]) + .clone(); + for _ in 0..64 { + print!("Bytes32(["); + for i in 0..32 { + print!("{}", empty_node[i]); + if i < 31 { + print!(", "); + } + } + println!("]),"); + empty_node = hash_node(MerkleType::Memory, empty_node, empty_node); + } + } + + #[test] + fn clone_is_separate() { + let merkle = Merkle::new_advanced(MerkleType::Value, vec![Bytes32::from([1; 32])], 4); + let m2 = merkle.clone(); + m2.resize(4).expect("resize failed"); + m2.set(3, Bytes32::from([2; 32])); + assert_ne!(merkle, m2); + } + + #[test] + fn serialization_roundtrip() { + let merkle = Merkle::new_advanced(MerkleType::Value, vec![Bytes32::from([1; 32])], 4); + merkle.resize(4).expect("resize failed"); + merkle.set(3, Bytes32::from([2; 32])); + let serialized = bincode::serialize(&merkle).unwrap(); + let deserialized: Merkle = bincode::deserialize(&serialized).unwrap(); + assert_eq!(merkle, deserialized); + } + + #[test] + #[should_panic(expected = "index out of bounds")] + fn set_with_bad_index_panics() { + let merkle = Merkle::new( + MerkleType::Value, + vec![Bytes32::default(), Bytes32::default()], + ); + assert_eq!(merkle.capacity(), 2); + merkle.set(2, Bytes32::default()); + } + + #[test] + fn test_zero_hashes() { + for ty in all::() { + if ty == MerkleType::Empty { + continue; } - let counterpart = layer - .get(idx ^ 1) - .cloned() - .unwrap_or_else(|| empty_layers[layer_i]); - if idx % 2 == 0 { - next_hash = hash_node(self.ty, next_hash, counterpart); - } else { - next_hash = hash_node(self.ty, counterpart, next_hash); + let mut empty_hash = Bytes32::from([0; 32]); + if ty == MerkleType::Memory { + empty_hash = memory::testing::empty_leaf_hash(); + } + for layer in 0..64 { + // empty_hash_at is just a lookup, but empty_hash is calculated iteratively. + assert_eq!(empty_hash_at(ty, layer), &empty_hash); + empty_hash = hash_node(ty, &empty_hash, &empty_hash); } - idx >>= 1; } } } diff --git a/arbitrator/prover/src/merkle/zerohashes.rs b/arbitrator/prover/src/merkle/zerohashes.rs new file mode 100644 index 0000000000..a4724a609d --- /dev/null +++ b/arbitrator/prover/src/merkle/zerohashes.rs @@ -0,0 +1,1827 @@ +use arbutil::Bytes32; + +const VALUE_HASHES: &[Bytes32; 64] = &[ + Bytes32([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + ]), + Bytes32([ + 119, 47, 167, 222, 218, 156, 26, 105, 57, 248, 170, 182, 183, 151, 18, 150, 142, 70, 138, + 253, 54, 123, 132, 86, 170, 76, 157, 52, 113, 138, 253, 254, + ]), + Bytes32([ + 8, 117, 27, 211, 196, 42, 6, 98, 185, 88, 231, 145, 14, 3, 207, 145, 158, 255, 69, 52, 198, + 196, 148, 154, 59, 94, 229, 157, 93, 51, 200, 69, + ]), + Bytes32([ + 247, 208, 196, 206, 204, 168, 129, 100, 238, 95, 52, 26, 132, 138, 233, 149, 196, 72, 179, + 226, 60, 114, 27, 94, 173, 189, 197, 100, 163, 232, 180, 63, + ]), + Bytes32([ + 178, 100, 198, 112, 40, 33, 187, 175, 130, 245, 59, 210, 133, 234, 158, 158, 133, 64, 213, + 72, 222, 157, 216, 42, 210, 134, 36, 13, 211, 156, 163, 211, + ]), + Bytes32([ + 203, 127, 32, 130, 225, 40, 219, 15, 35, 236, 47, 201, 161, 48, 53, 145, 134, 169, 109, 29, + 26, 29, 178, 201, 118, 217, 57, 165, 116, 172, 232, 4, + ]), + Bytes32([ + 209, 109, 33, 102, 227, 251, 133, 224, 170, 130, 65, 90, 185, 209, 146, 77, 244, 145, 181, + 206, 159, 70, 209, 64, 241, 19, 149, 223, 138, 31, 163, 61, + ]), + Bytes32([ + 145, 168, 124, 48, 254, 12, 34, 41, 4, 213, 245, 86, 61, 29, 177, 192, 67, 165, 237, 236, + 87, 126, 193, 191, 15, 126, 104, 173, 165, 186, 1, 107, + ]), + Bytes32([ + 235, 161, 247, 143, 69, 95, 210, 40, 243, 76, 102, 29, 118, 86, 180, 54, 81, 144, 103, 54, + 202, 164, 81, 83, 180, 90, 154, 184, 54, 28, 7, 220, + ]), + Bytes32([ + 203, 62, 12, 83, 35, 122, 214, 199, 125, 61, 236, 8, 253, 64, 145, 34, 127, 116, 217, 118, + 245, 107, 15, 81, 9, 7, 31, 154, 89, 28, 123, 132, + ]), + Bytes32([ + 222, 94, 234, 109, 142, 74, 142, 176, 248, 3, 172, 30, 204, 138, 241, 195, 121, 232, 104, + 219, 32, 54, 240, 77, 125, 247, 70, 137, 80, 46, 221, 247, + ]), + Bytes32([ + 162, 122, 237, 101, 178, 31, 12, 62, 50, 133, 242, 82, 111, 215, 166, 136, 138, 185, 72, + 220, 163, 58, 58, 97, 6, 97, 167, 114, 179, 227, 19, 170, + ]), + Bytes32([ + 67, 251, 144, 11, 175, 194, 149, 65, 173, 179, 69, 140, 213, 191, 133, 59, 81, 175, 161, + 115, 252, 125, 232, 150, 52, 241, 102, 164, 122, 32, 70, 229, + ]), + Bytes32([ + 249, 161, 115, 93, 215, 247, 145, 182, 75, 191, 48, 38, 123, 220, 232, 47, 246, 46, 81, + 164, 98, 41, 141, 249, 137, 173, 93, 213, 96, 15, 151, 245, + ]), + Bytes32([ + 222, 93, 144, 194, 107, 42, 144, 4, 242, 153, 203, 176, 146, 242, 94, 72, 9, 222, 194, 2, + 73, 200, 167, 147, 106, 9, 67, 73, 59, 127, 174, 178, + ]), + Bytes32([ + 56, 228, 248, 59, 153, 215, 120, 224, 111, 48, 159, 82, 171, 227, 93, 214, 208, 151, 78, + 67, 112, 31, 218, 94, 219, 3, 79, 250, 227, 24, 222, 207, + ]), + Bytes32([ + 26, 171, 68, 22, 162, 195, 65, 97, 219, 55, 51, 46, 178, 6, 247, 65, 123, 219, 128, 86, + 193, 3, 253, 0, 239, 228, 187, 94, 184, 240, 67, 11, + ]), + Bytes32([ + 250, 36, 5, 131, 94, 0, 99, 187, 112, 155, 252, 52, 68, 236, 185, 152, 93, 239, 0, 185, + 101, 101, 182, 92, 112, 5, 67, 55, 121, 203, 100, 245, + ]), + Bytes32([ + 208, 57, 149, 71, 227, 213, 246, 213, 175, 88, 95, 238, 93, 122, 168, 223, 149, 84, 30, 89, + 98, 228, 113, 72, 90, 48, 112, 171, 231, 67, 113, 216, + ]), + Bytes32([ + 125, 48, 157, 119, 154, 38, 14, 211, 223, 68, 87, 187, 159, 126, 234, 72, 84, 60, 236, 237, + 227, 130, 87, 43, 217, 105, 81, 196, 159, 238, 240, 10, + ]), + Bytes32([ + 141, 217, 59, 213, 245, 231, 7, 85, 178, 197, 115, 188, 31, 49, 126, 237, 83, 199, 56, 196, + 133, 169, 239, 218, 90, 131, 178, 70, 126, 132, 114, 186, + ]), + Bytes32([ + 18, 2, 140, 12, 121, 238, 8, 160, 7, 208, 89, 194, 105, 136, 211, 58, 179, 200, 226, 138, + 186, 242, 4, 237, 18, 113, 131, 135, 31, 222, 28, 195, + ]), + Bytes32([ + 156, 222, 183, 39, 119, 110, 130, 60, 33, 221, 36, 39, 223, 155, 33, 2, 71, 32, 209, 25, + 194, 172, 209, 1, 40, 105, 235, 140, 160, 18, 63, 168, + ]), + Bytes32([ + 211, 210, 123, 27, 217, 111, 97, 42, 167, 191, 112, 239, 66, 42, 199, 131, 124, 213, 89, + 56, 92, 245, 166, 238, 185, 42, 48, 2, 113, 255, 156, 7, + ]), + Bytes32([ + 66, 255, 87, 69, 86, 6, 54, 162, 162, 5, 93, 138, 194, 194, 151, 195, 57, 155, 58, 17, 21, + 149, 77, 2, 134, 107, 125, 54, 220, 247, 160, 209, + ]), + Bytes32([ + 169, 216, 13, 41, 251, 216, 191, 87, 91, 55, 236, 6, 242, 103, 98, 209, 46, 202, 29, 55, 2, + 50, 233, 76, 107, 92, 82, 156, 113, 226, 78, 211, + ]), + Bytes32([ + 88, 189, 113, 129, 119, 11, 141, 60, 128, 134, 113, 107, 7, 186, 81, 200, 14, 76, 197, 14, + 96, 19, 247, 220, 95, 62, 81, 153, 61, 231, 26, 86, + ]), + Bytes32([ + 41, 214, 41, 96, 151, 11, 231, 7, 203, 70, 242, 156, 247, 133, 49, 223, 254, 164, 202, 154, + 188, 104, 124, 120, 225, 229, 148, 203, 141, 218, 228, 56, + ]), + Bytes32([ + 181, 157, 136, 110, 158, 152, 105, 61, 125, 220, 32, 180, 53, 115, 155, 189, 91, 152, 96, + 172, 7, 121, 65, 143, 82, 180, 3, 69, 118, 219, 31, 244, + ]), + Bytes32([ + 29, 12, 159, 30, 12, 37, 126, 102, 218, 149, 67, 116, 182, 125, 134, 208, 184, 199, 181, + 191, 87, 144, 48, 150, 87, 67, 222, 218, 254, 118, 12, 160, + ]), + Bytes32([ + 193, 249, 209, 245, 102, 95, 15, 55, 160, 156, 203, 160, 49, 198, 203, 30, 99, 172, 89, 92, + 235, 89, 131, 205, 53, 254, 219, 168, 202, 195, 10, 242, + ]), + Bytes32([ + 131, 64, 102, 7, 226, 96, 60, 111, 221, 120, 41, 86, 239, 157, 121, 38, 57, 244, 221, 55, + 32, 237, 13, 20, 244, 238, 133, 189, 89, 118, 204, 247, + ]), + Bytes32([ + 239, 211, 89, 185, 191, 211, 243, 207, 134, 159, 59, 19, 87, 254, 115, 27, 152, 156, 120, + 226, 39, 63, 155, 51, 77, 130, 162, 63, 16, 43, 112, 121, + ]), + Bytes32([ + 10, 146, 190, 23, 235, 67, 23, 169, 33, 140, 54, 209, 129, 176, 29, 218, 40, 55, 13, 80, + 57, 68, 92, 97, 44, 82, 209, 240, 207, 214, 22, 119, + ]), + Bytes32([ + 59, 161, 125, 95, 7, 155, 141, 55, 253, 106, 238, 72, 109, 158, 201, 200, 236, 157, 227, + 178, 176, 47, 166, 84, 87, 111, 25, 133, 194, 55, 244, 254, + ]), + Bytes32([ + 8, 134, 213, 182, 108, 15, 225, 138, 152, 138, 132, 240, 27, 80, 231, 117, 194, 157, 205, + 20, 110, 239, 166, 37, 50, 46, 213, 165, 216, 101, 245, 98, + ]), + Bytes32([ + 137, 57, 186, 173, 198, 113, 221, 42, 0, 211, 127, 200, 128, 7, 112, 97, 75, 155, 152, 224, + 71, 220, 16, 124, 32, 50, 30, 48, 251, 132, 120, 147, + ]), + Bytes32([ + 201, 8, 226, 108, 147, 192, 3, 240, 168, 237, 131, 47, 150, 51, 251, 126, 23, 182, 223, 99, + 162, 167, 248, 248, 233, 8, 121, 99, 71, 212, 120, 251, + ]), + Bytes32([ + 140, 30, 196, 244, 166, 80, 95, 116, 140, 218, 94, 20, 236, 233, 241, 129, 175, 187, 110, + 88, 174, 173, 152, 203, 67, 75, 51, 232, 225, 6, 17, 134, + ]), + Bytes32([ + 92, 132, 115, 164, 66, 159, 201, 147, 233, 228, 16, 95, 81, 233, 129, 254, 155, 148, 38, + 239, 186, 40, 118, 104, 144, 134, 17, 46, 99, 150, 211, 9, + ]), + Bytes32([ + 81, 73, 72, 117, 215, 159, 240, 86, 136, 196, 69, 201, 149, 208, 48, 245, 105, 153, 97, + 107, 221, 85, 49, 121, 197, 129, 32, 140, 206, 231, 120, 123, + ]), + Bytes32([ + 0, 203, 34, 135, 242, 129, 113, 204, 198, 134, 219, 134, 187, 240, 235, 59, 44, 163, 180, + 83, 174, 40, 66, 141, 95, 99, 71, 221, 186, 216, 37, 250, + ]), + Bytes32([ + 225, 181, 151, 12, 26, 209, 127, 99, 248, 177, 126, 113, 215, 220, 252, 89, 149, 123, 19, + 65, 89, 122, 180, 169, 195, 87, 147, 9, 196, 31, 203, 178, + ]), + Bytes32([ + 125, 81, 154, 100, 204, 138, 194, 248, 156, 95, 119, 58, 60, 221, 150, 248, 216, 19, 123, + 15, 198, 108, 228, 228, 224, 122, 16, 249, 223, 84, 117, 89, + ]), + Bytes32([ + 99, 153, 60, 217, 168, 254, 244, 149, 214, 115, 250, 90, 117, 112, 66, 163, 143, 207, 121, + 70, 108, 92, 2, 47, 56, 109, 56, 207, 152, 27, 196, 141, + ]), + Bytes32([ + 99, 251, 124, 97, 158, 155, 101, 251, 98, 124, 239, 73, 50, 50, 173, 142, 39, 208, 167, 53, + 5, 151, 85, 239, 25, 77, 36, 52, 141, 225, 66, 186, + ]), + Bytes32([ + 235, 44, 31, 180, 197, 243, 114, 60, 199, 242, 167, 21, 206, 27, 116, 165, 18, 76, 162, + 163, 14, 91, 109, 104, 118, 51, 33, 172, 9, 165, 214, 38, + ]), + Bytes32([ + 188, 4, 5, 50, 169, 70, 231, 90, 220, 90, 226, 214, 89, 19, 159, 207, 201, 80, 241, 214, + 32, 240, 63, 74, 6, 251, 177, 182, 236, 19, 156, 92, + ]), + Bytes32([ + 128, 150, 66, 27, 197, 229, 103, 137, 175, 252, 19, 131, 213, 63, 112, 172, 182, 255, 235, + 246, 226, 37, 25, 180, 24, 38, 35, 138, 207, 149, 186, 175, + ]), + Bytes32([ + 5, 123, 231, 106, 12, 171, 157, 189, 58, 109, 144, 7, 38, 97, 4, 148, 1, 138, 124, 123, 2, + 202, 108, 221, 194, 160, 53, 73, 115, 36, 231, 142, + ]), + Bytes32([ + 160, 157, 243, 224, 214, 120, 59, 206, 24, 30, 231, 209, 123, 227, 15, 221, 86, 30, 128, + 117, 210, 109, 132, 117, 204, 87, 243, 213, 231, 224, 91, 75, + ]), + Bytes32([ + 74, 238, 110, 147, 63, 110, 246, 102, 252, 212, 120, 225, 124, 218, 145, 204, 129, 63, 13, + 34, 1, 0, 15, 9, 27, 221, 39, 199, 24, 231, 9, 38, + ]), + Bytes32([ + 194, 20, 160, 161, 90, 2, 118, 75, 103, 228, 51, 42, 191, 220, 63, 150, 140, 32, 85, 172, + 218, 29, 251, 31, 99, 96, 98, 46, 130, 157, 201, 61, + ]), + Bytes32([ + 88, 123, 95, 139, 94, 66, 69, 27, 223, 223, 216, 130, 99, 210, 130, 54, 248, 35, 226, 252, + 151, 238, 7, 175, 12, 97, 188, 43, 233, 129, 82, 222, + ]), + Bytes32([ + 179, 248, 157, 243, 50, 157, 172, 17, 139, 10, 245, 208, 241, 210, 67, 199, 135, 233, 234, + 39, 127, 38, 54, 39, 40, 159, 94, 122, 36, 221, 180, 195, + ]), + Bytes32([ + 190, 185, 147, 237, 82, 32, 165, 236, 252, 183, 173, 181, 68, 44, 216, 20, 110, 243, 158, + 213, 88, 209, 218, 207, 244, 241, 121, 239, 136, 167, 245, 155, + ]), + Bytes32([ + 114, 131, 254, 248, 183, 0, 175, 217, 194, 58, 178, 238, 250, 119, 158, 205, 19, 74, 94, + 35, 100, 175, 114, 55, 186, 192, 239, 126, 42, 86, 60, 119, + ]), + Bytes32([ + 1, 253, 107, 150, 25, 240, 27, 172, 252, 185, 151, 152, 107, 105, 164, 230, 221, 242, 7, + 166, 142, 53, 237, 83, 19, 30, 81, 149, 150, 39, 123, 220, + ]), + Bytes32([ + 57, 240, 92, 232, 26, 238, 69, 252, 110, 171, 164, 109, 199, 73, 110, 49, 11, 253, 109, 69, + 155, 26, 84, 52, 155, 204, 115, 99, 90, 38, 247, 167, + ]), + Bytes32([ + 46, 87, 146, 25, 215, 40, 208, 78, 73, 60, 35, 19, 194, 41, 34, 186, 215, 131, 205, 29, + 107, 100, 95, 169, 45, 1, 242, 115, 30, 226, 93, 48, + ]), + Bytes32([ + 95, 183, 66, 0, 196, 173, 44, 27, 175, 151, 17, 0, 159, 168, 123, 236, 124, 198, 85, 181, + 118, 89, 21, 52, 169, 104, 178, 111, 120, 173, 94, 109, + ]), + Bytes32([ + 13, 111, 162, 25, 133, 108, 250, 75, 197, 221, 19, 160, 147, 36, 130, 70, 224, 39, 134, + 144, 149, 166, 187, 96, 155, 154, 123, 90, 241, 154, 44, 102, + ]), + Bytes32([ + 95, 171, 183, 135, 121, 205, 161, 160, 212, 226, 64, 232, 180, 166, 176, 95, 51, 96, 110, + 20, 76, 143, 47, 96, 197, 132, 210, 109, 174, 132, 13, 95, + ]), + Bytes32([ + 66, 51, 176, 1, 106, 199, 192, 16, 106, 180, 212, 53, 72, 121, 218, 148, 77, 26, 15, 244, + 124, 131, 88, 84, 147, 211, 254, 156, 187, 91, 193, 120, + ]), +]; + +const FUNCTION_HASHES: &[Bytes32; 64] = &[ + Bytes32([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + ]), + Bytes32([ + 239, 247, 49, 255, 201, 159, 228, 149, 22, 115, 41, 139, 56, 117, 149, 46, 67, 155, 98, 70, + 216, 225, 85, 100, 113, 242, 144, 167, 97, 238, 117, 207, + ]), + Bytes32([ + 46, 87, 136, 101, 122, 12, 6, 120, 39, 121, 167, 193, 66, 146, 150, 1, 90, 240, 97, 225, + 179, 150, 197, 127, 56, 214, 116, 24, 180, 109, 96, 51, + ]), + Bytes32([ + 54, 125, 90, 195, 243, 1, 115, 18, 251, 68, 203, 216, 48, 156, 216, 200, 215, 250, 80, 152, + 203, 58, 245, 128, 70, 112, 221, 104, 34, 125, 234, 138, + ]), + Bytes32([ + 103, 99, 44, 86, 57, 0, 102, 201, 99, 214, 249, 24, 45, 112, 234, 183, 225, 196, 9, 162, + 168, 33, 121, 118, 93, 184, 14, 70, 148, 135, 211, 214, + ]), + Bytes32([ + 69, 7, 89, 47, 41, 94, 148, 139, 67, 197, 99, 98, 100, 63, 25, 230, 100, 118, 213, 25, 28, + 129, 5, 39, 69, 89, 71, 21, 102, 84, 101, 175, + ]), + Bytes32([ + 232, 195, 82, 123, 189, 200, 139, 61, 179, 141, 208, 69, 102, 58, 127, 66, 69, 127, 7, 179, + 108, 128, 253, 154, 207, 254, 201, 18, 192, 241, 99, 208, + ]), + Bytes32([ + 138, 25, 185, 215, 159, 159, 214, 251, 161, 103, 180, 78, 209, 215, 131, 132, 134, 180, + 177, 37, 79, 219, 19, 93, 45, 30, 53, 125, 142, 194, 114, 34, + ]), + Bytes32([ + 185, 24, 200, 28, 68, 7, 118, 226, 65, 240, 85, 120, 123, 174, 239, 85, 247, 210, 104, 247, + 20, 229, 41, 91, 242, 5, 2, 121, 132, 69, 43, 33, + ]), + Bytes32([ + 78, 191, 92, 97, 205, 120, 114, 216, 112, 101, 44, 98, 148, 2, 112, 221, 168, 199, 254, 55, + 160, 116, 116, 105, 109, 227, 130, 219, 194, 32, 209, 196, + ]), + Bytes32([ + 177, 203, 26, 1, 216, 115, 242, 158, 202, 107, 60, 221, 81, 167, 8, 233, 247, 235, 49, 54, + 45, 133, 202, 193, 34, 158, 205, 29, 232, 245, 195, 194, + ]), + Bytes32([ + 193, 118, 182, 153, 10, 237, 67, 229, 136, 193, 253, 250, 46, 125, 141, 22, 107, 168, 74, + 130, 60, 193, 194, 196, 249, 129, 153, 82, 162, 143, 188, 42, + ]), + Bytes32([ + 239, 57, 105, 90, 116, 61, 160, 214, 55, 191, 17, 228, 44, 149, 103, 180, 229, 4, 175, 240, + 209, 231, 141, 95, 109, 195, 78, 142, 122, 177, 227, 20, + ]), + Bytes32([ + 153, 247, 105, 126, 178, 44, 190, 57, 12, 63, 169, 27, 206, 19, 151, 38, 33, 83, 35, 3, + 177, 97, 36, 182, 37, 78, 150, 243, 222, 32, 180, 148, + ]), + Bytes32([ + 29, 109, 110, 167, 27, 136, 235, 226, 147, 175, 241, 236, 138, 135, 163, 200, 21, 94, 220, + 238, 23, 84, 46, 14, 44, 100, 47, 131, 134, 43, 98, 173, + ]), + Bytes32([ + 73, 241, 108, 102, 184, 200, 64, 80, 58, 162, 29, 211, 173, 150, 6, 195, 2, 137, 246, 51, + 155, 132, 41, 255, 21, 71, 74, 143, 197, 180, 217, 159, + ]), + Bytes32([ + 109, 189, 226, 33, 70, 157, 161, 166, 223, 31, 224, 221, 37, 112, 27, 215, 163, 250, 217, + 155, 168, 121, 119, 232, 100, 177, 104, 210, 10, 118, 215, 0, + ]), + Bytes32([ + 175, 156, 32, 156, 238, 82, 62, 25, 96, 251, 146, 24, 13, 2, 115, 174, 163, 50, 14, 251, + 196, 173, 5, 87, 171, 228, 191, 9, 90, 84, 156, 63, + ]), + Bytes32([ + 244, 161, 238, 217, 14, 60, 162, 139, 34, 84, 68, 121, 213, 11, 230, 95, 57, 221, 174, 107, + 103, 105, 76, 137, 58, 247, 65, 209, 167, 63, 96, 212, + ]), + Bytes32([ + 31, 177, 221, 130, 152, 92, 190, 4, 59, 90, 122, 63, 128, 180, 140, 201, 75, 239, 200, 151, + 94, 65, 36, 227, 21, 250, 10, 253, 26, 114, 238, 188, + ]), + Bytes32([ + 48, 216, 87, 30, 113, 214, 69, 1, 9, 112, 244, 232, 127, 55, 43, 162, 156, 83, 235, 199, + 126, 132, 241, 106, 65, 209, 240, 32, 11, 179, 219, 135, + ]), + Bytes32([ + 20, 55, 225, 132, 0, 219, 175, 17, 235, 73, 236, 16, 24, 227, 250, 155, 32, 83, 234, 123, + 191, 209, 157, 133, 215, 202, 3, 221, 135, 223, 221, 90, + ]), + Bytes32([ + 113, 185, 118, 164, 139, 219, 203, 140, 245, 123, 21, 186, 102, 22, 54, 14, 19, 230, 223, + 120, 211, 114, 203, 77, 173, 214, 61, 80, 151, 10, 2, 205, + ]), + Bytes32([ + 50, 20, 214, 105, 232, 5, 9, 101, 16, 72, 46, 139, 177, 188, 25, 93, 14, 57, 60, 168, 49, + 147, 134, 5, 62, 181, 120, 75, 193, 229, 107, 67, + ]), + Bytes32([ + 92, 167, 117, 18, 186, 193, 28, 56, 86, 25, 75, 64, 1, 8, 126, 212, 56, 163, 157, 242, 34, + 73, 65, 58, 187, 2, 112, 58, 225, 229, 113, 58, + ]), + Bytes32([ + 173, 139, 156, 215, 250, 231, 15, 123, 8, 5, 98, 192, 164, 48, 106, 203, 152, 189, 118, + 120, 245, 221, 214, 26, 79, 39, 148, 232, 217, 88, 34, 246, + ]), + Bytes32([ + 8, 207, 11, 196, 253, 51, 182, 90, 62, 110, 125, 142, 209, 154, 5, 203, 252, 62, 117, 215, + 226, 136, 140, 201, 227, 210, 71, 34, 113, 160, 42, 68, + ]), + Bytes32([ + 108, 135, 226, 117, 179, 142, 93, 181, 20, 186, 189, 217, 49, 154, 66, 244, 180, 170, 122, + 233, 153, 214, 104, 71, 44, 57, 103, 240, 97, 80, 170, 198, + ]), + Bytes32([ + 123, 168, 184, 254, 241, 78, 23, 91, 32, 77, 218, 176, 179, 189, 61, 162, 114, 158, 212, 7, + 201, 15, 58, 4, 161, 211, 188, 156, 190, 2, 20, 183, + ]), + Bytes32([ + 60, 170, 86, 130, 38, 170, 202, 88, 97, 206, 67, 69, 140, 122, 201, 38, 70, 229, 144, 202, + 146, 10, 146, 148, 21, 247, 119, 196, 150, 223, 110, 67, + ]), + Bytes32([ + 102, 154, 215, 132, 143, 248, 151, 101, 101, 253, 80, 211, 254, 64, 179, 73, 96, 132, 144, + 216, 225, 130, 48, 56, 14, 39, 97, 223, 134, 10, 124, 138, + ]), + Bytes32([ + 197, 131, 194, 166, 168, 160, 24, 116, 47, 120, 89, 3, 44, 154, 83, 250, 142, 64, 77, 63, + 15, 60, 97, 100, 150, 39, 227, 139, 42, 146, 146, 104, + ]), + Bytes32([ + 7, 160, 246, 93, 64, 79, 76, 208, 66, 80, 60, 123, 13, 51, 115, 251, 196, 209, 145, 106, + 61, 105, 136, 58, 7, 129, 142, 203, 205, 69, 45, 203, + ]), + Bytes32([ + 64, 162, 48, 187, 213, 182, 41, 85, 62, 148, 26, 161, 227, 108, 173, 249, 195, 106, 203, + 18, 28, 59, 184, 85, 249, 16, 224, 222, 114, 200, 99, 22, + ]), + Bytes32([ + 246, 194, 74, 122, 165, 216, 211, 144, 101, 143, 134, 9, 53, 229, 197, 227, 121, 248, 89, + 169, 48, 220, 104, 216, 117, 118, 36, 234, 108, 135, 81, 162, + ]), + Bytes32([ + 232, 59, 196, 2, 103, 242, 44, 129, 41, 231, 226, 115, 238, 151, 166, 210, 158, 110, 43, + 45, 86, 163, 127, 8, 162, 81, 131, 145, 165, 252, 170, 12, + ]), + Bytes32([ + 204, 88, 102, 180, 241, 148, 27, 183, 223, 71, 157, 119, 155, 31, 102, 239, 4, 83, 204, + 246, 38, 228, 234, 20, 97, 233, 203, 149, 186, 67, 143, 51, + ]), + Bytes32([ + 246, 170, 233, 8, 202, 38, 67, 219, 175, 13, 250, 174, 98, 36, 84, 166, 6, 75, 27, 43, 62, + 128, 106, 23, 163, 191, 86, 115, 164, 50, 127, 151, + ]), + Bytes32([ + 204, 72, 199, 57, 106, 136, 244, 66, 217, 155, 183, 211, 166, 71, 140, 211, 210, 181, 178, + 218, 204, 91, 200, 204, 153, 60, 22, 32, 24, 153, 131, 31, + ]), + Bytes32([ + 204, 193, 13, 167, 214, 136, 121, 99, 198, 137, 11, 223, 85, 40, 167, 126, 153, 80, 187, + 35, 226, 31, 226, 42, 9, 175, 31, 206, 119, 67, 153, 39, + ]), + Bytes32([ + 63, 82, 16, 182, 255, 45, 123, 220, 252, 52, 199, 222, 76, 172, 123, 232, 133, 182, 143, + 202, 223, 161, 203, 91, 239, 225, 123, 184, 231, 53, 19, 253, + ]), + Bytes32([ + 5, 13, 255, 217, 70, 105, 205, 70, 41, 25, 44, 3, 245, 136, 16, 255, 101, 61, 189, 225, + 142, 201, 210, 226, 9, 237, 171, 109, 63, 204, 204, 139, + ]), + Bytes32([ + 161, 218, 126, 252, 32, 196, 32, 105, 98, 13, 201, 117, 64, 37, 232, 32, 159, 106, 48, 121, + 250, 139, 219, 137, 129, 3, 83, 194, 102, 251, 148, 71, + ]), + Bytes32([ + 72, 17, 9, 21, 142, 89, 135, 91, 81, 155, 72, 247, 56, 232, 136, 57, 251, 182, 211, 35, + 207, 169, 87, 123, 31, 222, 72, 85, 212, 92, 159, 171, + ]), + Bytes32([ + 193, 253, 238, 224, 198, 216, 154, 52, 59, 87, 183, 80, 242, 162, 238, 7, 218, 195, 253, + 210, 92, 116, 43, 181, 109, 40, 74, 38, 154, 211, 102, 173, + ]), + Bytes32([ + 193, 88, 249, 81, 11, 128, 242, 239, 220, 1, 237, 199, 235, 12, 153, 73, 145, 158, 15, 111, + 108, 244, 19, 51, 159, 206, 66, 25, 147, 215, 157, 165, + ]), + Bytes32([ + 195, 90, 0, 163, 8, 199, 55, 59, 47, 117, 186, 204, 5, 42, 205, 164, 239, 233, 203, 210, + 69, 205, 244, 152, 113, 184, 206, 110, 101, 197, 120, 101, + ]), + Bytes32([ + 114, 169, 222, 11, 169, 15, 123, 245, 42, 25, 120, 198, 66, 140, 125, 123, 201, 107, 3, 50, + 245, 226, 52, 46, 162, 44, 134, 157, 226, 11, 115, 186, + ]), + Bytes32([ + 6, 47, 131, 89, 216, 138, 92, 250, 126, 232, 238, 50, 181, 78, 69, 115, 227, 25, 49, 50, + 116, 138, 47, 61, 179, 75, 121, 124, 127, 106, 228, 178, + ]), + Bytes32([ + 152, 253, 228, 228, 120, 255, 82, 66, 24, 145, 159, 223, 39, 185, 81, 201, 81, 110, 47, 57, + 105, 128, 8, 42, 130, 119, 92, 7, 14, 247, 137, 135, + ]), + Bytes32([ + 162, 28, 11, 245, 48, 21, 8, 137, 161, 131, 84, 18, 129, 70, 197, 122, 165, 39, 71, 213, + 142, 115, 159, 52, 46, 213, 81, 10, 217, 212, 74, 20, + ]), + Bytes32([ + 129, 250, 71, 119, 46, 25, 220, 212, 143, 120, 0, 101, 85, 101, 109, 107, 142, 20, 107, + 174, 39, 134, 128, 244, 237, 155, 190, 19, 110, 10, 240, 94, + ]), + Bytes32([ + 90, 70, 190, 48, 191, 45, 227, 17, 185, 162, 159, 12, 18, 94, 186, 251, 252, 238, 95, 174, + 253, 99, 194, 204, 5, 178, 117, 139, 50, 154, 93, 170, + ]), + Bytes32([ + 201, 8, 48, 126, 70, 22, 83, 82, 229, 84, 168, 86, 100, 169, 227, 175, 196, 154, 217, 150, + 2, 36, 1, 100, 48, 216, 141, 205, 113, 148, 109, 126, + ]), + Bytes32([ + 16, 182, 10, 119, 255, 70, 127, 242, 64, 68, 67, 44, 52, 195, 63, 185, 227, 97, 138, 244, + 53, 246, 110, 99, 41, 176, 146, 206, 81, 168, 66, 140, + ]), + Bytes32([ + 95, 9, 211, 227, 219, 119, 221, 132, 248, 92, 236, 190, 110, 227, 153, 109, 103, 63, 121, + 221, 165, 212, 20, 141, 33, 95, 52, 157, 69, 76, 2, 70, + ]), + Bytes32([ + 216, 138, 115, 198, 102, 135, 226, 247, 235, 185, 206, 147, 130, 9, 48, 166, 92, 22, 41, + 158, 169, 52, 233, 1, 60, 229, 165, 208, 60, 161, 194, 166, + ]), + Bytes32([ + 129, 241, 87, 138, 103, 241, 79, 26, 52, 35, 125, 237, 54, 147, 253, 137, 101, 146, 235, + 127, 124, 113, 60, 203, 181, 4, 250, 12, 72, 27, 24, 7, + ]), + Bytes32([ + 52, 120, 68, 97, 147, 229, 251, 178, 161, 233, 142, 136, 38, 40, 85, 46, 121, 156, 115, + 186, 72, 95, 128, 43, 252, 176, 176, 51, 113, 83, 154, 232, + ]), + Bytes32([ + 227, 11, 188, 57, 98, 160, 248, 247, 112, 49, 247, 92, 94, 224, 135, 182, 211, 230, 69, + 185, 138, 154, 141, 157, 18, 34, 138, 236, 67, 243, 26, 132, + ]), + Bytes32([ + 61, 246, 31, 52, 44, 146, 190, 215, 214, 105, 253, 86, 172, 174, 140, 112, 30, 154, 82, + 173, 62, 199, 157, 180, 255, 104, 73, 136, 163, 79, 210, 252, + ]), + Bytes32([ + 200, 155, 200, 87, 142, 123, 62, 176, 250, 44, 18, 238, 229, 121, 125, 109, 102, 173, 60, + 203, 88, 65, 33, 122, 22, 111, 157, 143, 164, 7, 214, 26, + ]), + Bytes32([ + 179, 76, 168, 179, 139, 86, 151, 173, 26, 70, 236, 116, 202, 123, 63, 80, 106, 208, 63, + 138, 179, 225, 114, 64, 48, 34, 78, 124, 132, 210, 224, 190, + ]), + Bytes32([ + 138, 116, 89, 240, 28, 79, 42, 149, 199, 118, 149, 49, 146, 212, 104, 62, 17, 137, 138, + 223, 225, 187, 152, 43, 134, 60, 95, 55, 175, 128, 95, 144, + ]), +]; + +const INSTRUCTION_HASHES: &[Bytes32; 64] = &[ + Bytes32([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + ]), + Bytes32([ + 248, 140, 83, 29, 241, 220, 66, 40, 126, 248, 5, 153, 77, 179, 26, 64, 221, 108, 205, 162, + 173, 52, 179, 140, 202, 105, 0, 170, 166, 130, 120, 176, + ]), + Bytes32([ + 35, 74, 103, 235, 245, 71, 66, 212, 99, 147, 15, 200, 1, 237, 95, 163, 10, 146, 122, 251, + 243, 239, 93, 186, 46, 74, 206, 130, 63, 17, 199, 80, + ]), + Bytes32([ + 113, 169, 40, 37, 169, 205, 28, 78, 37, 104, 52, 28, 29, 222, 39, 32, 208, 183, 215, 38, + 255, 69, 87, 70, 174, 113, 221, 183, 206, 62, 192, 118, + ]), + Bytes32([ + 1, 148, 183, 39, 234, 23, 138, 182, 169, 58, 52, 158, 248, 212, 186, 127, 60, 42, 25, 210, + 20, 170, 182, 139, 20, 185, 196, 85, 241, 214, 181, 64, + ]), + Bytes32([ + 241, 14, 59, 8, 168, 222, 232, 125, 149, 227, 125, 41, 223, 198, 88, 135, 54, 146, 140, + 212, 164, 76, 239, 106, 10, 20, 67, 180, 24, 159, 174, 99, + ]), + Bytes32([ + 117, 111, 220, 19, 204, 227, 211, 18, 61, 239, 179, 46, 142, 75, 67, 98, 159, 221, 205, + 158, 125, 42, 221, 227, 148, 162, 193, 229, 147, 70, 214, 127, + ]), + Bytes32([ + 20, 72, 211, 188, 38, 126, 166, 75, 54, 22, 225, 21, 113, 155, 167, 89, 161, 6, 37, 78, + 227, 211, 219, 141, 161, 199, 151, 122, 81, 45, 159, 187, + ]), + Bytes32([ + 69, 198, 100, 170, 106, 174, 208, 152, 152, 121, 118, 66, 111, 89, 131, 14, 159, 115, 142, + 200, 205, 173, 89, 77, 68, 234, 5, 171, 105, 248, 199, 83, + ]), + Bytes32([ + 17, 1, 220, 13, 154, 194, 88, 60, 253, 223, 149, 35, 44, 184, 107, 141, 205, 177, 185, 32, + 22, 99, 212, 96, 194, 91, 255, 179, 121, 153, 254, 40, + ]), + Bytes32([ + 222, 247, 186, 138, 222, 183, 135, 183, 170, 79, 182, 23, 69, 89, 70, 68, 88, 87, 235, 22, + 178, 134, 114, 220, 249, 153, 70, 71, 229, 139, 10, 190, + ]), + Bytes32([ + 183, 77, 65, 51, 207, 78, 55, 149, 222, 3, 100, 82, 232, 230, 21, 115, 249, 177, 36, 89, + 12, 41, 70, 31, 199, 254, 213, 3, 184, 2, 85, 137, + ]), + Bytes32([ + 82, 15, 215, 135, 95, 18, 143, 49, 239, 237, 6, 15, 213, 113, 153, 49, 149, 54, 50, 139, + 100, 192, 128, 226, 168, 9, 120, 167, 157, 42, 45, 19, + ]), + Bytes32([ + 70, 32, 130, 243, 186, 144, 224, 217, 130, 222, 175, 221, 218, 190, 179, 222, 217, 115, 70, + 160, 141, 231, 221, 96, 2, 173, 27, 17, 158, 66, 180, 58, + ]), + Bytes32([ + 76, 243, 65, 235, 12, 31, 48, 195, 62, 176, 202, 57, 99, 80, 237, 222, 138, 199, 124, 251, + 143, 243, 205, 226, 18, 164, 67, 64, 68, 238, 53, 71, + ]), + Bytes32([ + 70, 52, 254, 193, 211, 92, 63, 238, 92, 2, 160, 29, 154, 25, 221, 136, 2, 49, 96, 27, 15, + 152, 238, 57, 241, 253, 32, 131, 73, 38, 229, 243, + ]), + Bytes32([ + 214, 162, 82, 44, 146, 145, 61, 77, 36, 3, 131, 81, 217, 39, 127, 81, 66, 82, 172, 230, + 246, 3, 243, 217, 210, 38, 201, 109, 240, 143, 253, 79, + ]), + Bytes32([ + 127, 18, 198, 116, 112, 141, 16, 39, 115, 118, 37, 208, 118, 119, 147, 46, 196, 124, 19, + 196, 34, 183, 172, 157, 18, 91, 4, 210, 77, 195, 220, 59, + ]), + Bytes32([ + 87, 54, 42, 60, 39, 223, 84, 148, 158, 230, 70, 53, 191, 1, 108, 103, 139, 111, 58, 220, + 114, 46, 46, 110, 20, 211, 84, 1, 173, 104, 175, 191, + ]), + Bytes32([ + 182, 147, 66, 127, 229, 144, 125, 93, 84, 220, 116, 107, 51, 13, 24, 161, 68, 172, 165, 50, + 12, 198, 229, 173, 49, 26, 114, 159, 84, 190, 6, 42, + ]), + Bytes32([ + 183, 20, 36, 145, 76, 36, 61, 136, 224, 139, 89, 23, 124, 29, 210, 137, 1, 160, 22, 128, + 48, 242, 234, 85, 84, 24, 206, 49, 143, 185, 237, 110, + ]), + Bytes32([ + 38, 19, 77, 150, 92, 129, 177, 155, 139, 162, 90, 91, 231, 146, 216, 21, 54, 152, 18, 5, + 98, 21, 67, 160, 154, 113, 175, 65, 214, 78, 19, 97, + ]), + Bytes32([ + 163, 236, 47, 120, 121, 17, 217, 4, 200, 247, 206, 178, 211, 212, 163, 48, 38, 172, 111, + 123, 75, 221, 63, 117, 42, 3, 252, 233, 104, 13, 210, 203, + ]), + Bytes32([ + 127, 106, 132, 246, 28, 129, 245, 83, 159, 109, 196, 219, 68, 81, 230, 77, 254, 166, 55, + 73, 169, 179, 93, 97, 117, 176, 53, 74, 121, 238, 184, 240, + ]), + Bytes32([ + 255, 23, 108, 186, 145, 182, 196, 67, 163, 95, 173, 17, 67, 239, 199, 189, 145, 153, 120, + 152, 159, 126, 255, 39, 55, 178, 230, 173, 91, 165, 229, 106, + ]), + Bytes32([ + 184, 156, 20, 114, 222, 219, 89, 218, 102, 62, 130, 200, 179, 237, 32, 237, 127, 75, 251, + 163, 160, 2, 221, 34, 166, 30, 172, 97, 115, 137, 179, 175, + ]), + Bytes32([ + 244, 165, 127, 27, 66, 22, 38, 243, 235, 107, 30, 181, 31, 193, 210, 174, 254, 129, 39, 71, + 59, 117, 186, 37, 217, 129, 138, 23, 146, 114, 96, 78, + ]), + Bytes32([ + 27, 57, 244, 93, 208, 90, 64, 181, 161, 110, 161, 188, 62, 180, 46, 103, 136, 233, 63, 1, + 243, 202, 236, 206, 173, 45, 45, 218, 238, 184, 83, 121, + ]), + Bytes32([ + 138, 185, 33, 206, 120, 214, 246, 27, 100, 91, 106, 213, 60, 177, 39, 182, 149, 204, 11, + 225, 254, 5, 87, 9, 19, 186, 166, 210, 33, 67, 146, 37, + ]), + Bytes32([ + 243, 161, 7, 52, 35, 240, 227, 144, 29, 50, 232, 3, 101, 174, 192, 139, 89, 75, 204, 245, + 173, 55, 139, 76, 126, 19, 142, 18, 230, 57, 219, 227, + ]), + Bytes32([ + 97, 73, 36, 70, 120, 55, 49, 114, 107, 193, 66, 219, 47, 122, 201, 194, 52, 142, 12, 163, + 108, 2, 107, 58, 185, 251, 168, 146, 57, 189, 150, 134, + ]), + Bytes32([ + 11, 215, 29, 229, 151, 208, 62, 1, 172, 253, 253, 156, 177, 31, 117, 214, 161, 192, 68, + 255, 140, 131, 66, 23, 247, 161, 107, 98, 199, 57, 123, 110, + ]), + Bytes32([ + 41, 166, 54, 134, 242, 64, 153, 167, 5, 230, 226, 128, 71, 10, 251, 160, 19, 187, 70, 4, + 95, 98, 77, 233, 181, 24, 11, 239, 142, 152, 229, 215, + ]), + Bytes32([ + 221, 220, 68, 168, 143, 124, 235, 77, 241, 190, 214, 6, 102, 40, 32, 245, 131, 114, 170, + 151, 134, 49, 79, 57, 242, 124, 85, 172, 83, 81, 68, 99, + ]), + Bytes32([ + 142, 200, 102, 97, 170, 43, 14, 11, 139, 207, 150, 163, 99, 103, 2, 46, 44, 63, 109, 61, + 62, 64, 199, 104, 36, 194, 155, 232, 139, 250, 97, 224, + ]), + Bytes32([ + 162, 15, 26, 217, 96, 195, 70, 196, 253, 70, 127, 156, 39, 120, 120, 232, 197, 154, 192, + 147, 104, 33, 104, 189, 120, 160, 36, 129, 208, 237, 128, 23, + ]), + Bytes32([ + 42, 228, 74, 47, 20, 55, 197, 252, 173, 70, 178, 8, 2, 43, 97, 238, 155, 124, 87, 225, 217, + 6, 103, 134, 136, 235, 193, 175, 33, 228, 219, 217, + ]), + Bytes32([ + 219, 143, 25, 70, 78, 155, 119, 63, 126, 20, 158, 54, 27, 181, 104, 184, 74, 192, 75, 157, + 42, 204, 45, 122, 25, 248, 247, 24, 225, 207, 51, 251, + ]), + Bytes32([ + 151, 253, 36, 33, 104, 222, 126, 234, 112, 74, 59, 94, 239, 58, 36, 114, 90, 195, 208, 46, + 250, 138, 165, 200, 178, 54, 238, 154, 219, 238, 6, 183, + ]), + Bytes32([ + 205, 57, 187, 174, 221, 9, 164, 77, 76, 143, 54, 212, 115, 196, 67, 182, 200, 147, 78, 194, + 245, 92, 173, 114, 180, 160, 168, 5, 200, 82, 217, 64, + ]), + Bytes32([ + 211, 104, 62, 114, 157, 56, 254, 26, 32, 168, 208, 248, 62, 195, 142, 68, 53, 13, 7, 36, + 216, 5, 127, 153, 97, 88, 222, 206, 91, 42, 14, 114, + ]), + Bytes32([ + 203, 158, 225, 200, 62, 223, 202, 52, 207, 179, 250, 236, 29, 144, 181, 31, 87, 192, 203, + 66, 56, 39, 123, 25, 123, 157, 196, 161, 34, 245, 22, 130, + ]), + Bytes32([ + 147, 247, 233, 96, 190, 104, 227, 251, 99, 2, 16, 8, 77, 119, 1, 97, 243, 78, 103, 46, 24, + 228, 217, 65, 219, 238, 135, 18, 164, 219, 132, 39, + ]), + Bytes32([ + 239, 153, 72, 139, 52, 60, 171, 44, 72, 218, 138, 124, 45, 30, 143, 122, 147, 158, 12, 62, + 213, 151, 217, 217, 212, 51, 110, 75, 122, 67, 134, 80, + ]), + Bytes32([ + 46, 47, 130, 237, 178, 232, 239, 217, 165, 114, 255, 202, 132, 214, 18, 8, 72, 8, 255, 0, + 162, 82, 5, 228, 141, 201, 70, 135, 255, 21, 220, 3, + ]), + Bytes32([ + 21, 11, 196, 5, 215, 241, 194, 200, 198, 129, 133, 244, 204, 47, 131, 70, 138, 38, 107, 39, + 211, 243, 72, 72, 34, 145, 35, 42, 14, 69, 218, 227, + ]), + Bytes32([ + 73, 103, 117, 195, 67, 126, 242, 57, 232, 74, 142, 64, 169, 248, 113, 69, 110, 103, 127, + 185, 177, 51, 212, 178, 48, 183, 247, 44, 246, 69, 35, 208, + ]), + Bytes32([ + 125, 8, 83, 22, 215, 82, 179, 234, 169, 227, 213, 39, 170, 164, 195, 187, 63, 38, 59, 146, + 144, 101, 38, 0, 110, 212, 202, 20, 245, 105, 187, 201, + ]), + Bytes32([ + 186, 231, 186, 148, 68, 208, 226, 170, 120, 80, 68, 79, 23, 41, 51, 205, 240, 201, 10, 16, + 24, 38, 137, 151, 7, 102, 92, 244, 3, 194, 228, 229, + ]), + Bytes32([ + 46, 8, 51, 150, 63, 114, 126, 210, 30, 130, 76, 142, 13, 149, 14, 0, 205, 199, 48, 90, 86, + 75, 151, 135, 164, 224, 129, 77, 174, 194, 212, 112, + ]), + Bytes32([ + 150, 239, 42, 111, 3, 112, 25, 168, 179, 36, 106, 73, 212, 188, 215, 79, 180, 142, 191, 29, + 219, 12, 244, 74, 254, 205, 160, 54, 68, 144, 81, 207, + ]), + Bytes32([ + 23, 164, 189, 201, 250, 65, 212, 148, 132, 125, 94, 209, 115, 123, 29, 66, 3, 172, 57, 58, + 46, 191, 96, 7, 212, 25, 226, 79, 120, 68, 202, 210, + ]), + Bytes32([ + 252, 13, 137, 225, 208, 6, 84, 75, 97, 32, 177, 156, 248, 191, 113, 97, 254, 122, 86, 194, + 3, 103, 219, 74, 227, 160, 231, 202, 13, 126, 46, 255, + ]), + Bytes32([ + 70, 35, 27, 128, 17, 79, 226, 131, 144, 118, 248, 125, 188, 110, 20, 15, 255, 73, 205, 69, + 0, 227, 26, 66, 39, 61, 191, 224, 239, 234, 83, 170, + ]), + Bytes32([ + 129, 52, 148, 121, 230, 84, 28, 112, 75, 68, 181, 197, 80, 227, 107, 22, 60, 118, 81, 209, + 198, 125, 233, 190, 84, 189, 18, 25, 72, 143, 2, 190, + ]), + Bytes32([ + 244, 237, 81, 131, 251, 35, 56, 158, 229, 102, 150, 122, 213, 206, 119, 38, 54, 238, 158, + 159, 1, 214, 31, 147, 245, 9, 172, 247, 156, 115, 209, 140, + ]), + Bytes32([ + 47, 5, 174, 62, 80, 172, 77, 111, 136, 114, 188, 85, 249, 157, 182, 175, 187, 207, 29, 43, + 152, 88, 130, 156, 138, 30, 188, 51, 82, 105, 145, 161, + ]), + Bytes32([ + 102, 2, 197, 195, 206, 149, 53, 224, 61, 219, 163, 246, 208, 218, 140, 47, 16, 42, 196, 20, + 145, 158, 101, 31, 225, 135, 49, 68, 95, 5, 228, 92, + ]), + Bytes32([ + 78, 136, 176, 216, 253, 15, 136, 48, 162, 5, 57, 120, 93, 222, 179, 174, 129, 40, 8, 63, + 18, 102, 97, 41, 58, 214, 1, 52, 58, 126, 186, 146, + ]), + Bytes32([ + 145, 56, 231, 59, 247, 191, 104, 137, 240, 113, 32, 245, 235, 129, 255, 54, 99, 176, 109, + 175, 107, 232, 201, 235, 95, 104, 54, 67, 252, 184, 200, 54, + ]), + Bytes32([ + 181, 3, 229, 152, 113, 182, 55, 93, 138, 137, 21, 67, 27, 204, 96, 69, 72, 247, 237, 216, + 28, 36, 115, 185, 111, 149, 224, 69, 66, 121, 188, 228, + ]), + Bytes32([ + 212, 25, 201, 68, 187, 25, 10, 96, 40, 88, 100, 216, 145, 200, 26, 203, 220, 14, 14, 11, + 190, 62, 143, 137, 53, 208, 233, 158, 37, 34, 8, 15, + ]), + Bytes32([ + 80, 101, 192, 136, 203, 90, 189, 204, 181, 36, 28, 107, 220, 69, 119, 99, 145, 227, 198, + 55, 37, 237, 212, 114, 31, 27, 19, 90, 231, 143, 87, 149, + ]), + Bytes32([ + 248, 97, 168, 33, 15, 230, 128, 82, 157, 26, 186, 89, 200, 7, 101, 210, 117, 111, 75, 233, + 244, 187, 1, 180, 30, 220, 15, 21, 203, 5, 243, 223, + ]), +]; + +/// These have been pre-calculated to match the current implementation of Memory::hash_leaf. +const MEMORY_HASHES: &[Bytes32; 64] = &[ + Bytes32([ + 57, 29, 211, 154, 252, 227, 18, 99, 65, 126, 203, 166, 252, 232, 32, 3, 98, 194, 254, 186, + 118, 14, 139, 192, 101, 156, 55, 194, 101, 11, 11, 168, + ]), + Bytes32([ + 190, 70, 141, 125, 34, 236, 162, 217, 92, 130, 99, 237, 252, 176, 62, 93, 182, 71, 180, + 204, 178, 127, 225, 18, 119, 68, 89, 244, 245, 143, 151, 9, + ]), + Bytes32([ + 9, 87, 12, 3, 155, 102, 114, 211, 160, 40, 161, 7, 3, 192, 11, 145, 241, 17, 215, 209, 18, + 230, 221, 198, 189, 52, 34, 224, 245, 121, 253, 194, + ]), + Bytes32([ + 10, 61, 178, 250, 4, 50, 245, 174, 54, 189, 184, 161, 208, 164, 55, 145, 70, 4, 81, 28, + 129, 97, 216, 23, 41, 192, 91, 97, 9, 83, 1, 215, + ]), + Bytes32([ + 244, 167, 192, 124, 155, 131, 227, 49, 180, 187, 181, 23, 114, 255, 114, 237, 129, 149, + 159, 244, 63, 138, 0, 237, 37, 38, 159, 106, 4, 153, 119, 255, + ]), + Bytes32([ + 63, 174, 225, 251, 118, 10, 96, 200, 132, 107, 27, 128, 250, 62, 47, 221, 227, 241, 107, + 254, 3, 171, 26, 81, 199, 162, 154, 249, 154, 72, 185, 196, + ]), + Bytes32([ + 89, 112, 167, 92, 33, 192, 100, 158, 137, 92, 61, 197, 73, 216, 188, 164, 72, 37, 5, 0, + 161, 144, 254, 18, 10, 4, 248, 174, 26, 5, 149, 142, + ]), + Bytes32([ + 202, 243, 125, 81, 15, 253, 233, 83, 91, 186, 151, 205, 84, 225, 16, 241, 42, 27, 7, 15, + 143, 128, 189, 233, 206, 106, 21, 7, 96, 167, 149, 2, + ]), + Bytes32([ + 155, 19, 224, 94, 41, 7, 172, 244, 76, 43, 181, 160, 220, 80, 64, 0, 140, 33, 238, 79, 87, + 43, 40, 34, 162, 57, 122, 232, 216, 48, 64, 114, + ]), + Bytes32([ + 64, 199, 52, 187, 21, 58, 215, 47, 174, 163, 203, 89, 35, 199, 187, 86, 137, 145, 236, 145, + 66, 21, 218, 151, 88, 61, 109, 238, 61, 58, 215, 247, + ]), + Bytes32([ + 197, 59, 74, 219, 191, 151, 46, 252, 54, 248, 228, 94, 22, 143, 69, 197, 114, 247, 37, 212, + 243, 158, 179, 192, 205, 50, 50, 36, 40, 130, 115, 247, + ]), + Bytes32([ + 168, 115, 30, 246, 210, 241, 88, 129, 115, 193, 107, 199, 199, 35, 118, 28, 145, 183, 82, + 101, 162, 52, 67, 147, 208, 234, 115, 58, 40, 124, 16, 79, + ]), + Bytes32([ + 253, 6, 238, 29, 37, 160, 45, 23, 26, 114, 137, 254, 44, 68, 147, 33, 212, 149, 16, 188, + 28, 174, 189, 22, 12, 228, 99, 101, 60, 248, 174, 34, + ]), + Bytes32([ + 0, 89, 208, 120, 115, 63, 79, 9, 29, 16, 81, 231, 78, 251, 117, 98, 172, 207, 54, 97, 38, + 72, 37, 110, 102, 207, 38, 198, 165, 157, 208, 6, + ]), + Bytes32([ + 193, 144, 83, 148, 50, 15, 138, 224, 145, 12, 222, 94, 88, 91, 151, 74, 180, 47, 102, 38, + 244, 38, 251, 13, 230, 130, 141, 133, 10, 194, 108, 211, + ]), + Bytes32([ + 182, 202, 171, 144, 153, 127, 43, 239, 77, 89, 56, 144, 39, 180, 30, 164, 1, 120, 105, 55, + 21, 17, 147, 96, 185, 219, 67, 146, 86, 42, 44, 117, + ]), + Bytes32([ + 240, 76, 90, 37, 238, 134, 53, 105, 125, 238, 19, 80, 162, 60, 63, 104, 193, 201, 233, 10, + 246, 175, 15, 167, 239, 50, 201, 138, 153, 127, 40, 247, + ]), + Bytes32([ + 127, 96, 10, 125, 139, 9, 213, 13, 60, 75, 10, 85, 88, 169, 180, 24, 18, 171, 157, 161, + 252, 181, 178, 191, 227, 200, 140, 72, 205, 231, 67, 34, + ]), + Bytes32([ + 8, 81, 79, 192, 81, 171, 28, 73, 80, 93, 207, 58, 0, 192, 109, 40, 59, 227, 148, 172, 144, + 146, 237, 103, 47, 77, 112, 155, 215, 125, 49, 205, + ]), + Bytes32([ + 181, 244, 223, 157, 69, 161, 149, 150, 31, 65, 52, 113, 11, 233, 51, 145, 135, 161, 34, + 114, 133, 86, 133, 255, 161, 176, 170, 255, 21, 163, 146, 79, + ]), + Bytes32([ + 251, 112, 107, 186, 121, 118, 206, 118, 164, 136, 208, 159, 220, 188, 218, 111, 190, 44, + 16, 16, 251, 116, 206, 236, 111, 184, 20, 247, 252, 129, 200, 164, + ]), + Bytes32([ + 101, 111, 124, 218, 143, 90, 110, 65, 52, 118, 81, 72, 234, 164, 106, 84, 54, 136, 212, + 192, 46, 87, 56, 241, 227, 38, 37, 101, 250, 134, 254, 144, + ]), + Bytes32([ + 209, 232, 185, 167, 159, 116, 4, 11, 114, 98, 71, 225, 233, 246, 135, 173, 175, 126, 125, + 101, 16, 27, 254, 198, 79, 21, 181, 120, 50, 139, 76, 4, + ]), + Bytes32([ + 30, 122, 82, 142, 43, 26, 170, 27, 0, 177, 218, 106, 39, 13, 154, 151, 92, 47, 144, 113, + 173, 242, 169, 89, 230, 135, 188, 190, 57, 170, 66, 220, + ]), + Bytes32([ + 39, 137, 200, 154, 57, 148, 82, 232, 82, 214, 232, 251, 187, 13, 253, 222, 184, 161, 144, + 231, 67, 116, 160, 231, 214, 47, 228, 88, 146, 14, 244, 108, + ]), + Bytes32([ + 122, 9, 214, 205, 84, 161, 177, 137, 68, 9, 178, 177, 141, 219, 162, 109, 116, 124, 124, + 56, 189, 139, 28, 220, 98, 165, 217, 156, 157, 148, 43, 232, + ]), + Bytes32([ + 83, 209, 1, 98, 176, 225, 170, 233, 144, 110, 148, 135, 159, 243, 202, 14, 201, 243, 218, + 255, 75, 90, 222, 25, 141, 148, 128, 132, 101, 8, 178, 180, + ]), + Bytes32([ + 93, 131, 135, 74, 118, 43, 37, 103, 218, 116, 47, 5, 212, 230, 133, 11, 76, 199, 46, 91, + 17, 222, 122, 114, 166, 228, 113, 213, 31, 5, 32, 164, + ]), + Bytes32([ + 230, 49, 245, 147, 146, 113, 214, 229, 67, 34, 234, 170, 14, 37, 33, 105, 12, 192, 127, + 177, 195, 70, 29, 44, 232, 191, 3, 56, 70, 40, 70, 69, + ]), + Bytes32([ + 64, 48, 103, 64, 135, 164, 51, 233, 201, 62, 5, 28, 35, 183, 178, 104, 54, 238, 0, 58, 215, + 157, 29, 149, 57, 23, 224, 247, 85, 104, 240, 113, + ]), + Bytes32([ + 12, 156, 88, 246, 58, 5, 82, 65, 113, 178, 127, 112, 138, 170, 91, 11, 79, 54, 122, 65, 87, + 104, 104, 93, 134, 176, 56, 5, 139, 142, 73, 54, + ]), + Bytes32([ + 92, 41, 81, 165, 165, 210, 34, 91, 127, 46, 250, 148, 104, 192, 211, 77, 108, 49, 111, 57, + 161, 242, 142, 46, 100, 47, 24, 24, 51, 219, 92, 186, + ]), + Bytes32([ + 201, 120, 116, 179, 124, 183, 117, 97, 200, 35, 138, 235, 77, 177, 138, 42, 47, 58, 69, + 188, 70, 2, 71, 95, 51, 233, 69, 14, 22, 24, 195, 153, + ]), + Bytes32([ + 249, 189, 13, 189, 45, 69, 100, 141, 50, 145, 24, 54, 91, 45, 125, 223, 181, 222, 63, 49, + 66, 49, 106, 175, 55, 85, 112, 25, 69, 187, 44, 171, + ]), + Bytes32([ + 86, 114, 135, 219, 78, 73, 34, 205, 239, 144, 56, 231, 164, 101, 129, 115, 51, 167, 158, + 96, 1, 241, 178, 216, 54, 84, 97, 185, 200, 239, 215, 7, + ]), + Bytes32([ + 35, 232, 131, 249, 70, 6, 185, 10, 58, 53, 72, 254, 74, 166, 76, 41, 122, 234, 77, 61, 16, + 39, 26, 66, 102, 78, 102, 159, 55, 113, 195, 19, + ]), + Bytes32([ + 204, 120, 229, 250, 86, 164, 18, 58, 82, 11, 112, 225, 76, 253, 63, 35, 245, 72, 81, 254, + 193, 182, 255, 159, 200, 120, 135, 60, 253, 180, 185, 112, + ]), + Bytes32([ + 35, 194, 73, 72, 85, 35, 3, 215, 21, 38, 67, 254, 195, 250, 173, 177, 156, 70, 47, 13, 178, + 120, 227, 214, 92, 71, 181, 40, 213, 43, 193, 147, + ]), + Bytes32([ + 148, 91, 40, 131, 45, 85, 232, 203, 101, 47, 189, 225, 128, 118, 138, 12, 83, 98, 227, 166, + 192, 69, 188, 19, 84, 13, 162, 250, 65, 209, 47, 191, + ]), + Bytes32([ + 100, 36, 35, 232, 157, 164, 39, 175, 77, 211, 19, 26, 20, 226, 226, 255, 121, 134, 19, 46, + 185, 213, 2, 4, 6, 92, 47, 239, 206, 240, 225, 58, + ]), + Bytes32([ + 121, 36, 6, 138, 185, 33, 130, 28, 55, 238, 127, 203, 99, 32, 56, 245, 237, 135, 207, 190, + 72, 243, 137, 32, 218, 103, 150, 171, 3, 246, 48, 225, + ]), + Bytes32([ + 233, 56, 238, 34, 238, 134, 69, 104, 220, 255, 47, 202, 241, 144, 207, 249, 107, 153, 38, + 120, 101, 12, 177, 64, 151, 114, 146, 6, 227, 159, 40, 107, + ]), + Bytes32([ + 237, 115, 194, 93, 160, 113, 23, 120, 250, 186, 21, 163, 155, 20, 179, 177, 55, 20, 24, 89, + 77, 113, 163, 0, 176, 130, 228, 133, 239, 122, 177, 65, + ]), + Bytes32([ + 108, 150, 128, 44, 189, 57, 148, 254, 56, 134, 118, 165, 95, 15, 168, 179, 162, 252, 169, + 58, 223, 20, 38, 221, 25, 138, 101, 131, 32, 8, 2, 58, + ]), + Bytes32([ + 154, 13, 160, 129, 192, 79, 86, 40, 135, 113, 123, 38, 53, 254, 62, 94, 255, 14, 119, 4, + 102, 168, 200, 191, 112, 245, 29, 200, 164, 155, 141, 139, + ]), + Bytes32([ + 238, 189, 209, 174, 202, 251, 240, 99, 133, 44, 221, 34, 17, 88, 220, 143, 188, 160, 235, + 121, 167, 96, 106, 249, 213, 176, 31, 84, 26, 144, 201, 89, + ]), + Bytes32([ + 178, 186, 146, 221, 228, 41, 150, 76, 220, 216, 144, 64, 108, 178, 242, 120, 153, 191, 212, + 37, 114, 21, 30, 117, 45, 238, 46, 19, 132, 212, 112, 44, + ]), + Bytes32([ + 191, 19, 180, 171, 125, 68, 104, 43, 66, 173, 194, 168, 213, 192, 117, 82, 167, 41, 139, + 133, 92, 103, 124, 85, 241, 66, 1, 154, 68, 72, 171, 80, + ]), + Bytes32([ + 79, 215, 118, 157, 123, 16, 70, 30, 101, 234, 117, 41, 35, 186, 99, 5, 232, 45, 253, 142, + 185, 18, 172, 187, 36, 50, 218, 252, 111, 184, 158, 254, + ]), + Bytes32([ + 17, 193, 206, 44, 67, 98, 171, 63, 78, 209, 71, 20, 196, 255, 64, 114, 191, 19, 246, 131, + 8, 105, 211, 169, 192, 114, 249, 240, 28, 55, 230, 143, + ]), + Bytes32([ + 200, 94, 187, 80, 140, 194, 238, 35, 62, 228, 202, 122, 136, 119, 228, 133, 33, 147, 161, + 218, 94, 19, 207, 129, 48, 252, 242, 19, 56, 251, 92, 76, + ]), + Bytes32([ + 223, 124, 52, 170, 180, 101, 70, 1, 153, 22, 178, 138, 181, 253, 35, 113, 159, 136, 77, 23, + 158, 62, 11, 48, 6, 185, 147, 81, 220, 191, 94, 3, + ]), + Bytes32([ + 126, 124, 205, 157, 16, 239, 172, 241, 70, 70, 205, 98, 211, 8, 84, 204, 149, 9, 208, 56, + 122, 51, 224, 231, 200, 59, 41, 215, 141, 183, 91, 223, + ]), + Bytes32([ + 20, 122, 156, 134, 248, 95, 140, 199, 59, 151, 120, 164, 109, 202, 165, 126, 108, 161, 8, + 253, 18, 35, 36, 83, 219, 162, 58, 83, 136, 57, 43, 35, + ]), + Bytes32([ + 58, 175, 246, 31, 114, 109, 109, 219, 230, 129, 128, 99, 175, 228, 65, 148, 53, 233, 226, + 171, 44, 254, 222, 211, 200, 28, 193, 130, 251, 152, 160, 210, + ]), + Bytes32([ + 177, 255, 19, 82, 14, 229, 84, 206, 156, 198, 252, 176, 126, 211, 226, 255, 154, 231, 131, + 158, 165, 154, 142, 166, 131, 221, 203, 30, 251, 205, 27, 217, + ]), + Bytes32([ + 32, 168, 192, 93, 240, 173, 218, 42, 78, 215, 104, 243, 154, 2, 50, 159, 21, 176, 28, 59, + 29, 57, 193, 122, 32, 244, 91, 148, 91, 184, 126, 31, + ]), + Bytes32([ + 28, 66, 164, 117, 43, 120, 84, 240, 48, 3, 55, 95, 44, 229, 231, 29, 217, 67, 49, 130, 110, + 209, 72, 71, 46, 208, 63, 81, 218, 98, 167, 207, + ]), + Bytes32([ + 38, 192, 60, 175, 136, 217, 168, 69, 90, 236, 62, 137, 9, 116, 244, 151, 181, 57, 229, 198, + 100, 125, 114, 46, 80, 136, 150, 94, 225, 162, 170, 91, + ]), + Bytes32([ + 121, 67, 11, 63, 56, 140, 67, 231, 175, 126, 41, 37, 252, 62, 35, 215, 250, 206, 190, 3, + 154, 83, 237, 174, 65, 86, 83, 251, 110, 8, 44, 216, + ]), + Bytes32([ + 25, 251, 117, 251, 14, 64, 166, 211, 216, 123, 38, 1, 98, 19, 119, 194, 60, 234, 185, 148, + 118, 201, 4, 233, 69, 135, 13, 191, 8, 6, 136, 240, + ]), + Bytes32([ + 137, 1, 201, 130, 166, 152, 216, 48, 178, 242, 46, 3, 66, 92, 4, 81, 11, 145, 205, 82, 253, + 102, 78, 6, 53, 13, 36, 171, 48, 75, 165, 153, + ]), + Bytes32([ + 126, 38, 201, 183, 226, 145, 26, 196, 124, 127, 185, 12, 77, 198, 146, 16, 202, 189, 113, + 44, 100, 87, 81, 53, 172, 227, 97, 191, 120, 241, 86, 110, + ]), + Bytes32([ + 45, 8, 41, 170, 235, 127, 133, 14, 253, 53, 201, 220, 96, 192, 168, 234, 110, 20, 174, 226, + 18, 4, 230, 182, 204, 99, 138, 27, 82, 209, 28, 68, + ]), +]; + +const TABLE_HASHES: &[Bytes32; 64] = &[ + Bytes32([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + ]), + Bytes32([ + 164, 47, 121, 69, 150, 44, 30, 204, 210, 181, 242, 154, 59, 111, 5, 10, 47, 121, 213, 80, + 163, 196, 205, 188, 241, 64, 202, 26, 242, 47, 50, 205, + ]), + Bytes32([ + 166, 9, 224, 145, 14, 138, 194, 78, 202, 114, 110, 38, 244, 33, 189, 185, 170, 85, 144, + 229, 123, 63, 229, 194, 59, 130, 156, 6, 184, 154, 187, 17, + ]), + Bytes32([ + 32, 51, 186, 232, 39, 244, 218, 98, 243, 254, 82, 247, 63, 120, 34, 123, 128, 240, 220, + 145, 41, 114, 251, 208, 209, 244, 10, 9, 179, 5, 105, 181, + ]), + Bytes32([ + 73, 148, 74, 132, 241, 45, 129, 169, 83, 223, 101, 12, 184, 60, 10, 201, 169, 197, 75, 17, + 198, 168, 79, 171, 207, 195, 123, 47, 249, 30, 176, 216, + ]), + Bytes32([ + 145, 224, 51, 196, 211, 137, 189, 133, 232, 210, 170, 157, 227, 160, 218, 143, 15, 82, 170, + 226, 241, 83, 7, 112, 138, 227, 58, 59, 149, 168, 81, 94, + ]), + Bytes32([ + 241, 90, 42, 7, 231, 63, 36, 86, 238, 131, 19, 20, 38, 118, 65, 180, 109, 121, 147, 147, + 213, 142, 203, 244, 239, 75, 5, 160, 16, 85, 221, 95, + ]), + Bytes32([ + 213, 113, 178, 221, 213, 107, 77, 153, 222, 48, 148, 140, 250, 1, 17, 59, 73, 19, 110, 106, + 94, 195, 126, 49, 126, 109, 65, 55, 104, 111, 18, 171, + ]), + Bytes32([ + 43, 198, 12, 197, 95, 201, 76, 108, 96, 235, 76, 8, 117, 99, 42, 20, 177, 45, 112, 40, 2, + 180, 68, 19, 25, 11, 210, 168, 170, 178, 99, 27, + ]), + Bytes32([ + 142, 205, 24, 125, 81, 234, 138, 161, 206, 121, 163, 225, 50, 9, 180, 102, 0, 25, 93, 180, + 137, 164, 206, 249, 222, 20, 175, 177, 199, 14, 115, 207, + ]), + Bytes32([ + 213, 41, 249, 19, 173, 165, 236, 103, 42, 146, 223, 6, 190, 229, 161, 13, 96, 163, 110, 23, + 203, 238, 24, 95, 130, 203, 35, 211, 63, 234, 32, 137, + ]), + Bytes32([ + 176, 82, 229, 48, 113, 46, 179, 38, 231, 83, 50, 136, 179, 190, 242, 126, 152, 210, 141, + 102, 191, 21, 20, 96, 235, 245, 81, 254, 231, 117, 159, 146, + ]), + Bytes32([ + 216, 15, 120, 147, 70, 215, 12, 160, 223, 73, 246, 73, 195, 189, 200, 3, 19, 131, 102, 61, + 173, 79, 50, 76, 39, 150, 151, 147, 35, 251, 200, 0, + ]), + Bytes32([ + 88, 215, 168, 30, 218, 72, 206, 159, 91, 121, 14, 133, 241, 220, 195, 46, 93, 244, 179, 53, + 158, 75, 211, 161, 8, 120, 167, 141, 235, 16, 232, 42, + ]), + Bytes32([ + 114, 99, 218, 52, 203, 162, 199, 16, 225, 154, 182, 20, 59, 121, 250, 249, 166, 35, 118, + 18, 142, 57, 122, 131, 32, 219, 83, 126, 147, 91, 116, 16, + ]), + Bytes32([ + 193, 157, 15, 251, 179, 155, 215, 190, 98, 93, 30, 167, 23, 175, 178, 172, 142, 143, 222, + 20, 18, 157, 215, 42, 105, 107, 64, 16, 216, 143, 109, 45, + ]), + Bytes32([ + 178, 2, 203, 32, 83, 90, 114, 97, 124, 210, 81, 81, 179, 213, 71, 19, 181, 173, 227, 88, + 226, 83, 48, 169, 134, 163, 62, 103, 222, 82, 128, 30, + ]), + Bytes32([ + 252, 17, 142, 50, 185, 19, 111, 148, 204, 30, 199, 138, 143, 207, 30, 212, 254, 7, 129, 43, + 100, 167, 52, 115, 247, 143, 64, 106, 220, 5, 7, 89, + ]), + Bytes32([ + 117, 136, 111, 98, 95, 97, 253, 43, 82, 22, 43, 187, 65, 154, 132, 105, 55, 194, 240, 148, + 170, 199, 185, 91, 157, 138, 43, 117, 218, 176, 110, 101, + ]), + Bytes32([ + 228, 56, 186, 202, 73, 47, 253, 151, 48, 173, 2, 101, 153, 197, 108, 145, 227, 170, 247, + 86, 80, 70, 30, 93, 232, 148, 63, 211, 197, 135, 23, 97, + ]), + Bytes32([ + 162, 35, 93, 45, 208, 241, 87, 57, 138, 79, 231, 83, 75, 81, 102, 91, 115, 58, 1, 205, 193, + 197, 62, 210, 144, 88, 59, 52, 149, 234, 121, 224, + ]), + Bytes32([ + 165, 67, 16, 239, 234, 92, 207, 81, 64, 93, 227, 154, 132, 33, 54, 53, 102, 198, 90, 134, + 24, 29, 190, 158, 121, 23, 127, 30, 27, 239, 140, 88, + ]), + Bytes32([ + 61, 125, 183, 139, 186, 82, 193, 166, 2, 147, 231, 215, 179, 107, 163, 67, 122, 0, 90, 188, + 142, 216, 72, 20, 63, 146, 85, 89, 231, 41, 153, 117, + ]), + Bytes32([ + 206, 31, 38, 182, 78, 170, 183, 207, 211, 114, 212, 4, 108, 84, 62, 99, 245, 196, 10, 1, + 188, 63, 240, 199, 27, 85, 68, 101, 212, 222, 85, 12, + ]), + Bytes32([ + 106, 0, 225, 130, 195, 87, 113, 106, 101, 80, 56, 119, 93, 45, 74, 168, 240, 209, 155, 123, + 8, 129, 73, 225, 204, 125, 42, 73, 102, 122, 228, 158, + ]), + Bytes32([ + 251, 63, 88, 92, 59, 176, 71, 194, 46, 19, 18, 27, 83, 57, 197, 231, 202, 242, 155, 63, + 252, 240, 205, 216, 96, 130, 161, 197, 123, 110, 175, 220, + ]), + Bytes32([ + 239, 6, 249, 150, 189, 234, 197, 18, 79, 222, 80, 72, 205, 147, 251, 135, 226, 33, 46, 111, + 186, 185, 4, 33, 219, 129, 30, 182, 57, 229, 34, 16, + ]), + Bytes32([ + 192, 35, 149, 149, 16, 111, 3, 119, 173, 215, 223, 247, 70, 25, 31, 107, 104, 5, 249, 243, + 193, 66, 99, 48, 107, 158, 25, 147, 163, 151, 96, 149, + ]), + Bytes32([ + 197, 133, 241, 197, 67, 52, 255, 227, 180, 235, 137, 164, 174, 160, 183, 9, 159, 254, 210, + 180, 231, 140, 176, 165, 113, 215, 182, 1, 177, 204, 219, 246, + ]), + Bytes32([ + 51, 32, 109, 173, 131, 6, 99, 63, 75, 191, 207, 187, 73, 26, 5, 139, 167, 216, 123, 26, + 199, 176, 84, 215, 158, 243, 105, 0, 91, 254, 59, 146, + ]), + Bytes32([ + 229, 120, 15, 22, 225, 50, 131, 240, 190, 232, 83, 119, 169, 246, 172, 35, 99, 163, 58, + 146, 234, 253, 252, 83, 5, 48, 54, 142, 172, 91, 145, 13, + ]), + Bytes32([ + 159, 9, 100, 20, 215, 92, 217, 43, 208, 254, 65, 234, 124, 167, 250, 53, 159, 151, 124, 70, + 26, 0, 113, 28, 78, 44, 238, 8, 34, 255, 19, 36, + ]), + Bytes32([ + 193, 135, 44, 144, 13, 46, 76, 43, 127, 208, 79, 196, 229, 58, 125, 33, 71, 118, 215, 240, + 80, 123, 44, 181, 174, 47, 102, 42, 137, 98, 190, 41, + ]), + Bytes32([ + 78, 19, 3, 217, 174, 154, 142, 109, 189, 14, 241, 12, 23, 185, 224, 152, 209, 108, 223, + 202, 191, 11, 190, 149, 31, 236, 104, 234, 22, 38, 196, 3, + ]), + Bytes32([ + 60, 93, 237, 228, 186, 222, 179, 231, 151, 95, 147, 20, 188, 10, 191, 34, 126, 57, 253, + 161, 154, 117, 182, 108, 143, 72, 48, 102, 191, 240, 81, 208, + ]), + Bytes32([ + 179, 114, 163, 89, 172, 211, 154, 204, 11, 125, 140, 186, 107, 90, 17, 116, 214, 31, 165, + 94, 36, 187, 184, 151, 210, 208, 76, 215, 75, 166, 107, 91, + ]), + Bytes32([ + 125, 131, 52, 139, 120, 156, 163, 243, 206, 143, 204, 221, 123, 140, 1, 103, 235, 186, 64, + 82, 194, 191, 205, 2, 32, 242, 38, 77, 184, 23, 236, 228, + ]), + Bytes32([ + 137, 224, 90, 1, 116, 95, 215, 47, 8, 3, 227, 132, 154, 232, 216, 63, 3, 80, 52, 18, 42, + 29, 85, 38, 117, 255, 9, 99, 88, 233, 129, 92, + ]), + Bytes32([ + 54, 182, 145, 174, 54, 24, 168, 13, 71, 43, 178, 49, 153, 246, 94, 79, 228, 254, 134, 0, + 21, 210, 176, 242, 82, 117, 76, 40, 221, 181, 30, 62, + ]), + Bytes32([ + 145, 171, 156, 87, 15, 174, 31, 111, 175, 161, 31, 116, 123, 123, 37, 216, 43, 147, 197, + 79, 218, 49, 236, 111, 35, 49, 44, 188, 197, 79, 136, 45, + ]), + Bytes32([ + 169, 48, 186, 93, 10, 48, 80, 103, 68, 226, 103, 31, 176, 154, 146, 199, 166, 89, 48, 149, + 116, 101, 157, 149, 149, 72, 123, 54, 153, 26, 210, 122, + ]), + Bytes32([ + 225, 45, 163, 167, 213, 84, 40, 87, 106, 253, 206, 80, 189, 71, 153, 5, 15, 107, 151, 150, + 14, 22, 143, 207, 4, 192, 63, 250, 207, 207, 179, 26, + ]), + Bytes32([ + 110, 249, 172, 218, 206, 202, 107, 64, 48, 153, 226, 127, 165, 227, 50, 146, 140, 239, 220, + 252, 188, 157, 77, 210, 92, 73, 38, 6, 16, 87, 244, 66, + ]), + Bytes32([ + 39, 217, 230, 91, 60, 231, 96, 137, 37, 58, 93, 51, 79, 222, 132, 171, 196, 109, 155, 4, + 252, 213, 17, 33, 160, 24, 250, 118, 187, 62, 107, 113, + ]), + Bytes32([ + 120, 167, 145, 121, 184, 31, 185, 178, 241, 54, 20, 48, 132, 89, 132, 127, 235, 189, 197, + 127, 249, 58, 255, 197, 40, 229, 130, 254, 213, 186, 114, 74, + ]), + Bytes32([ + 7, 40, 187, 172, 225, 196, 3, 77, 113, 16, 118, 148, 95, 65, 42, 234, 233, 29, 120, 223, + 105, 77, 250, 119, 245, 20, 21, 155, 177, 13, 56, 151, + ]), + Bytes32([ + 22, 248, 25, 75, 36, 179, 251, 57, 101, 170, 213, 19, 216, 64, 164, 253, 151, 199, 88, 5, + 92, 129, 138, 185, 9, 236, 231, 68, 112, 24, 218, 216, + ]), + Bytes32([ + 95, 141, 49, 39, 213, 214, 130, 49, 143, 124, 178, 114, 200, 136, 160, 90, 233, 73, 233, + 185, 60, 250, 174, 74, 2, 123, 2, 62, 192, 174, 115, 158, + ]), + Bytes32([ + 142, 29, 212, 35, 71, 107, 91, 164, 226, 225, 180, 218, 99, 34, 200, 171, 33, 235, 113, + 105, 191, 78, 105, 70, 221, 135, 167, 148, 24, 225, 6, 146, + ]), + Bytes32([ + 176, 194, 115, 243, 138, 104, 3, 247, 184, 74, 81, 60, 173, 45, 29, 189, 252, 202, 206, 66, + 129, 65, 150, 25, 246, 145, 133, 4, 93, 201, 201, 240, + ]), + Bytes32([ + 18, 233, 186, 158, 43, 12, 206, 228, 80, 102, 187, 25, 78, 77, 180, 28, 82, 62, 168, 252, + 14, 113, 126, 91, 243, 120, 213, 91, 189, 244, 247, 177, + ]), + Bytes32([ + 79, 126, 97, 23, 112, 98, 93, 86, 24, 103, 82, 33, 155, 188, 202, 61, 29, 146, 132, 169, + 116, 207, 216, 35, 29, 229, 213, 120, 135, 240, 129, 205, + ]), + Bytes32([ + 146, 121, 255, 202, 145, 53, 46, 8, 102, 205, 56, 234, 49, 42, 85, 231, 217, 114, 235, 141, + 233, 187, 29, 9, 122, 232, 61, 253, 42, 104, 4, 113, + ]), + Bytes32([ + 103, 174, 255, 6, 115, 155, 156, 65, 84, 251, 208, 55, 89, 124, 171, 167, 133, 227, 22, + 134, 32, 71, 243, 181, 16, 100, 81, 63, 22, 207, 58, 190, + ]), + Bytes32([ + 69, 10, 247, 243, 56, 0, 64, 72, 218, 21, 211, 192, 62, 243, 66, 244, 230, 58, 107, 54, + 180, 29, 216, 23, 86, 211, 173, 181, 118, 188, 238, 72, + ]), + Bytes32([ + 25, 179, 4, 93, 169, 76, 76, 69, 158, 3, 24, 146, 130, 9, 225, 198, 102, 238, 29, 73, 74, + 179, 159, 74, 40, 111, 181, 110, 76, 173, 251, 255, + ]), + Bytes32([ + 236, 113, 37, 202, 149, 150, 90, 50, 233, 141, 125, 12, 212, 163, 137, 176, 15, 214, 194, + 73, 138, 104, 4, 33, 235, 76, 185, 58, 125, 182, 56, 0, + ]), + Bytes32([ + 238, 54, 183, 94, 50, 33, 98, 31, 133, 181, 230, 98, 43, 154, 95, 111, 250, 71, 15, 197, + 156, 60, 8, 90, 208, 50, 62, 127, 30, 18, 181, 176, + ]), + Bytes32([ + 246, 143, 72, 228, 143, 15, 15, 131, 178, 105, 113, 46, 85, 36, 165, 116, 63, 131, 61, 228, + 98, 144, 232, 209, 228, 110, 168, 171, 252, 47, 79, 165, + ]), + Bytes32([ + 146, 70, 74, 79, 139, 107, 73, 28, 231, 88, 235, 214, 163, 185, 87, 195, 147, 186, 153, + 222, 191, 214, 30, 231, 173, 166, 151, 169, 244, 15, 15, 227, + ]), + Bytes32([ + 137, 182, 175, 97, 212, 23, 62, 70, 50, 150, 67, 153, 253, 52, 179, 105, 147, 177, 217, + 170, 125, 251, 1, 96, 4, 127, 196, 37, 254, 7, 217, 100, + ]), + Bytes32([ + 32, 253, 229, 209, 120, 43, 120, 189, 245, 227, 178, 79, 134, 175, 240, 107, 25, 124, 5, + 67, 120, 213, 187, 200, 159, 9, 26, 119, 13, 1, 8, 120, + ]), + Bytes32([ + 115, 241, 26, 44, 83, 229, 130, 21, 249, 87, 72, 212, 75, 220, 95, 22, 151, 77, 182, 8, + 196, 207, 95, 18, 9, 92, 89, 206, 114, 80, 36, 159, + ]), + Bytes32([ + 174, 151, 88, 171, 52, 40, 161, 16, 106, 45, 44, 9, 142, 95, 5, 205, 82, 24, 172, 103, 152, + 202, 187, 34, 217, 173, 236, 129, 32, 203, 205, 38, + ]), +]; + +const TABLE_ELEMENT_HASHES: &[Bytes32; 64] = &[ + Bytes32([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + ]), + Bytes32([ + 145, 218, 63, 74, 131, 182, 204, 163, 74, 206, 234, 50, 47, 3, 51, 74, 121, 225, 146, 237, + 5, 128, 20, 230, 243, 89, 33, 248, 136, 154, 189, 5, + ]), + Bytes32([ + 36, 240, 95, 13, 214, 136, 92, 102, 96, 137, 39, 96, 108, 223, 147, 130, 220, 61, 147, 226, + 52, 133, 67, 223, 211, 164, 6, 53, 45, 117, 120, 241, + ]), + Bytes32([ + 9, 2, 218, 34, 228, 8, 178, 127, 160, 30, 104, 198, 49, 37, 71, 115, 14, 35, 20, 15, 253, + 160, 147, 143, 24, 186, 12, 90, 41, 169, 30, 8, + ]), + Bytes32([ + 137, 242, 105, 78, 161, 99, 76, 224, 226, 100, 216, 235, 156, 132, 214, 154, 107, 120, 197, + 113, 45, 221, 170, 119, 92, 228, 76, 139, 170, 159, 111, 58, + ]), + Bytes32([ + 231, 165, 221, 185, 139, 22, 70, 40, 67, 162, 123, 94, 161, 156, 57, 53, 102, 217, 128, + 227, 18, 132, 17, 170, 90, 31, 214, 181, 249, 220, 70, 37, + ]), + Bytes32([ + 171, 253, 174, 187, 9, 186, 87, 37, 22, 83, 13, 88, 75, 11, 177, 226, 237, 136, 132, 137, + 101, 109, 135, 192, 224, 80, 87, 105, 95, 81, 255, 21, + ]), + Bytes32([ + 179, 50, 36, 230, 159, 162, 184, 132, 140, 121, 133, 155, 189, 44, 132, 93, 80, 79, 32, + 244, 131, 57, 79, 222, 104, 63, 224, 182, 91, 162, 73, 122, + ]), + Bytes32([ + 17, 55, 206, 87, 127, 185, 135, 231, 41, 56, 166, 104, 229, 102, 222, 181, 236, 233, 230, + 39, 43, 163, 16, 1, 225, 86, 211, 51, 145, 7, 169, 84, + ]), + Bytes32([ + 201, 174, 3, 154, 104, 190, 240, 99, 123, 201, 7, 118, 196, 85, 28, 247, 35, 232, 39, 25, + 151, 52, 167, 136, 179, 13, 213, 60, 138, 158, 39, 131, + ]), + Bytes32([ + 35, 33, 109, 155, 171, 252, 195, 80, 10, 115, 40, 199, 250, 1, 241, 82, 146, 225, 118, 237, + 11, 125, 198, 97, 57, 21, 171, 237, 94, 60, 49, 32, + ]), + Bytes32([ + 126, 95, 42, 157, 183, 168, 137, 120, 114, 64, 148, 170, 32, 156, 137, 96, 194, 91, 119, + 11, 20, 3, 30, 62, 118, 12, 31, 48, 245, 144, 252, 29, + ]), + Bytes32([ + 48, 135, 201, 114, 103, 35, 8, 96, 5, 101, 125, 26, 87, 0, 98, 122, 239, 140, 230, 10, 102, + 112, 155, 87, 249, 181, 152, 235, 28, 79, 176, 56, + ]), + Bytes32([ + 76, 70, 222, 210, 242, 159, 52, 123, 112, 106, 253, 140, 55, 160, 189, 255, 220, 64, 8, + 168, 39, 196, 160, 8, 105, 154, 91, 184, 62, 63, 227, 156, + ]), + Bytes32([ + 138, 201, 8, 240, 218, 190, 210, 227, 236, 168, 45, 161, 209, 115, 126, 165, 235, 162, 6, + 117, 76, 239, 3, 225, 163, 251, 111, 233, 233, 228, 14, 92, + ]), + Bytes32([ + 190, 166, 27, 117, 242, 0, 25, 148, 230, 125, 237, 22, 153, 158, 151, 56, 121, 194, 221, + 198, 184, 147, 249, 149, 27, 29, 166, 243, 254, 181, 209, 102, + ]), + Bytes32([ + 235, 63, 149, 47, 164, 152, 80, 11, 178, 203, 99, 178, 176, 226, 164, 151, 39, 65, 83, 200, + 102, 90, 12, 102, 178, 15, 232, 16, 222, 141, 78, 3, + ]), + Bytes32([ + 37, 179, 99, 114, 214, 120, 87, 53, 198, 229, 207, 47, 16, 112, 208, 33, 216, 152, 209, + 228, 196, 14, 237, 250, 212, 90, 176, 185, 21, 248, 92, 109, + ]), + Bytes32([ + 237, 200, 122, 93, 145, 116, 138, 59, 86, 220, 58, 171, 160, 31, 142, 193, 231, 131, 106, + 164, 166, 44, 120, 170, 62, 81, 73, 85, 0, 52, 219, 220, + ]), + Bytes32([ + 244, 173, 85, 141, 81, 198, 214, 0, 54, 21, 20, 169, 177, 235, 104, 206, 43, 218, 96, 68, + 73, 37, 252, 77, 253, 18, 30, 97, 223, 122, 1, 12, + ]), + Bytes32([ + 104, 169, 247, 140, 131, 245, 193, 3, 36, 119, 249, 119, 108, 102, 115, 250, 173, 225, 33, + 156, 116, 87, 180, 27, 84, 215, 126, 15, 187, 189, 32, 139, + ]), + Bytes32([ + 47, 156, 244, 88, 145, 227, 224, 87, 233, 138, 138, 9, 169, 96, 29, 204, 100, 170, 23, 105, + 63, 4, 119, 90, 167, 161, 72, 109, 82, 254, 123, 48, + ]), + Bytes32([ + 196, 68, 107, 111, 141, 253, 138, 140, 162, 104, 247, 104, 87, 144, 123, 240, 105, 251, + 246, 210, 172, 172, 241, 162, 155, 90, 83, 175, 131, 251, 107, 215, + ]), + Bytes32([ + 28, 100, 243, 226, 32, 234, 211, 106, 197, 179, 14, 192, 70, 11, 203, 125, 151, 53, 20, 77, + 175, 99, 154, 100, 159, 249, 54, 39, 73, 168, 162, 66, + ]), + Bytes32([ + 83, 176, 7, 180, 201, 178, 172, 98, 47, 34, 80, 6, 62, 10, 4, 112, 43, 93, 10, 227, 74, 91, + 11, 217, 83, 230, 104, 0, 167, 2, 114, 89, + ]), + Bytes32([ + 185, 162, 212, 82, 149, 182, 104, 215, 62, 244, 114, 124, 181, 74, 226, 119, 4, 42, 181, + 238, 25, 212, 215, 219, 174, 231, 32, 170, 9, 234, 12, 212, + ]), + Bytes32([ + 173, 38, 241, 20, 137, 119, 33, 252, 174, 245, 252, 234, 165, 181, 128, 225, 14, 147, 182, + 97, 145, 19, 40, 193, 90, 238, 140, 87, 0, 222, 70, 254, + ]), + Bytes32([ + 51, 218, 162, 213, 211, 23, 9, 158, 185, 156, 39, 145, 5, 146, 70, 144, 172, 10, 26, 212, + 253, 37, 24, 32, 21, 65, 179, 140, 64, 237, 96, 157, + ]), + Bytes32([ + 221, 87, 57, 81, 246, 126, 53, 163, 190, 220, 109, 205, 114, 234, 85, 151, 75, 245, 254, + 16, 140, 131, 239, 120, 9, 209, 54, 61, 177, 6, 188, 252, + ]), + Bytes32([ + 54, 161, 25, 198, 75, 151, 214, 76, 83, 74, 117, 229, 155, 237, 88, 95, 143, 119, 56, 12, + 201, 164, 235, 20, 117, 49, 177, 88, 14, 248, 95, 198, + ]), + Bytes32([ + 60, 16, 183, 115, 241, 45, 253, 24, 105, 43, 79, 72, 212, 238, 24, 156, 132, 93, 78, 246, + 1, 228, 222, 200, 254, 130, 170, 46, 91, 254, 205, 143, + ]), + Bytes32([ + 184, 30, 34, 235, 214, 40, 120, 64, 182, 15, 162, 189, 164, 202, 89, 146, 202, 177, 16, + 105, 172, 158, 1, 95, 101, 146, 253, 115, 226, 233, 38, 171, + ]), + Bytes32([ + 70, 152, 3, 73, 249, 222, 93, 214, 74, 179, 140, 47, 34, 42, 149, 214, 152, 75, 34, 145, + 68, 226, 151, 101, 121, 54, 252, 240, 206, 140, 81, 165, + ]), + Bytes32([ + 9, 88, 51, 124, 67, 108, 84, 244, 61, 241, 110, 246, 184, 105, 6, 116, 242, 58, 15, 144, + 43, 76, 176, 107, 0, 138, 155, 235, 210, 138, 226, 215, + ]), + Bytes32([ + 98, 170, 168, 147, 158, 223, 186, 7, 58, 130, 89, 200, 153, 24, 158, 251, 69, 100, 7, 57, + 96, 115, 136, 170, 57, 145, 143, 240, 102, 6, 248, 111, + ]), + Bytes32([ + 76, 75, 216, 216, 194, 146, 2, 59, 247, 64, 98, 160, 62, 105, 193, 186, 161, 191, 64, 154, + 254, 196, 55, 214, 201, 103, 223, 131, 181, 192, 152, 176, + ]), + Bytes32([ + 188, 141, 114, 199, 33, 45, 183, 18, 123, 231, 92, 215, 51, 191, 11, 199, 253, 46, 28, 10, + 156, 23, 92, 255, 219, 236, 176, 247, 52, 105, 210, 223, + ]), + Bytes32([ + 200, 67, 112, 29, 180, 70, 50, 18, 220, 122, 39, 122, 83, 186, 81, 77, 241, 44, 190, 3, + 162, 217, 76, 61, 230, 237, 157, 230, 205, 172, 186, 247, + ]), + Bytes32([ + 131, 131, 129, 83, 251, 217, 83, 88, 93, 39, 66, 174, 51, 19, 190, 91, 16, 187, 95, 63, 35, + 178, 94, 237, 194, 42, 231, 227, 138, 202, 216, 93, + ]), + Bytes32([ + 18, 177, 28, 41, 199, 59, 160, 244, 26, 162, 73, 48, 16, 74, 190, 195, 249, 216, 64, 229, + 145, 65, 18, 131, 75, 57, 71, 74, 127, 239, 112, 13, + ]), + Bytes32([ + 41, 120, 53, 253, 151, 12, 143, 213, 212, 31, 245, 61, 168, 113, 30, 38, 112, 126, 156, + 133, 241, 102, 110, 237, 4, 138, 50, 160, 79, 235, 52, 35, + ]), + Bytes32([ + 38, 74, 146, 27, 110, 86, 122, 250, 58, 243, 64, 185, 207, 174, 28, 124, 35, 183, 53, 88, + 34, 234, 89, 58, 98, 223, 69, 13, 48, 15, 239, 230, + ]), + Bytes32([ + 221, 132, 1, 28, 157, 232, 235, 132, 32, 58, 26, 36, 60, 217, 197, 165, 141, 19, 64, 120, + 197, 139, 190, 86, 153, 152, 235, 11, 99, 129, 222, 91, + ]), + Bytes32([ + 237, 76, 61, 239, 169, 108, 131, 62, 163, 67, 158, 210, 14, 45, 91, 105, 36, 182, 206, 182, + 71, 11, 159, 169, 159, 248, 247, 176, 6, 176, 237, 123, + ]), + Bytes32([ + 232, 190, 198, 78, 12, 148, 86, 176, 221, 115, 1, 22, 122, 163, 223, 234, 74, 129, 125, 53, + 211, 137, 115, 18, 241, 170, 69, 42, 34, 74, 180, 172, + ]), + Bytes32([ + 215, 199, 144, 158, 222, 153, 123, 125, 150, 97, 127, 151, 96, 43, 69, 155, 150, 119, 75, + 82, 218, 48, 101, 70, 121, 18, 42, 146, 215, 183, 100, 158, + ]), + Bytes32([ + 121, 182, 45, 62, 255, 78, 32, 48, 107, 186, 208, 155, 158, 80, 231, 241, 90, 227, 219, + 113, 52, 20, 66, 45, 124, 67, 209, 61, 167, 74, 60, 34, + ]), + Bytes32([ + 34, 136, 15, 103, 128, 220, 202, 103, 150, 123, 249, 145, 218, 227, 17, 64, 142, 129, 4, + 42, 93, 7, 6, 147, 111, 117, 25, 185, 88, 104, 85, 115, + ]), + Bytes32([ + 144, 191, 235, 38, 205, 102, 127, 160, 139, 105, 75, 63, 86, 192, 194, 49, 240, 35, 65, + 154, 4, 113, 51, 87, 40, 70, 32, 58, 243, 16, 136, 67, + ]), + Bytes32([ + 217, 150, 254, 250, 111, 69, 45, 227, 111, 59, 199, 149, 59, 216, 17, 117, 8, 226, 85, 250, + 183, 187, 21, 129, 208, 0, 63, 158, 232, 106, 131, 16, + ]), + Bytes32([ + 148, 212, 84, 16, 204, 49, 69, 96, 137, 125, 102, 221, 111, 8, 41, 51, 221, 241, 87, 231, + 88, 215, 211, 24, 254, 131, 111, 56, 160, 143, 230, 109, + ]), + Bytes32([ + 144, 48, 37, 157, 153, 7, 123, 206, 46, 224, 211, 249, 208, 217, 91, 243, 128, 62, 100, + 126, 3, 253, 223, 161, 50, 108, 26, 151, 129, 242, 94, 132, + ]), + Bytes32([ + 97, 167, 177, 53, 183, 154, 164, 1, 129, 184, 234, 182, 190, 197, 244, 226, 150, 217, 57, + 152, 243, 206, 60, 76, 114, 194, 51, 240, 58, 93, 219, 76, + ]), + Bytes32([ + 139, 70, 147, 227, 94, 147, 130, 53, 38, 112, 138, 176, 7, 148, 6, 21, 50, 199, 70, 33, 87, + 180, 33, 167, 56, 89, 66, 95, 245, 247, 135, 24, + ]), + Bytes32([ + 175, 169, 204, 13, 145, 18, 40, 29, 84, 88, 206, 99, 208, 137, 249, 146, 0, 237, 188, 130, + 135, 223, 121, 54, 126, 251, 247, 109, 141, 217, 62, 127, + ]), + Bytes32([ + 139, 188, 3, 234, 198, 124, 194, 238, 217, 237, 214, 250, 66, 220, 0, 51, 1, 203, 122, 125, + 46, 213, 22, 253, 8, 218, 145, 253, 170, 156, 159, 96, + ]), + Bytes32([ + 107, 130, 208, 55, 16, 249, 46, 4, 98, 236, 130, 52, 190, 126, 232, 229, 108, 126, 239, + 175, 25, 229, 84, 33, 249, 66, 128, 162, 47, 221, 110, 163, + ]), + Bytes32([ + 239, 176, 14, 134, 210, 125, 177, 40, 200, 42, 229, 32, 200, 58, 9, 73, 210, 161, 8, 105, + 4, 70, 19, 134, 117, 132, 167, 18, 16, 108, 207, 113, + ]), + Bytes32([ + 237, 116, 250, 79, 151, 228, 171, 189, 89, 213, 122, 121, 55, 25, 52, 238, 79, 19, 31, 194, + 73, 158, 43, 78, 86, 194, 36, 141, 105, 10, 87, 58, + ]), + Bytes32([ + 216, 125, 158, 123, 121, 158, 74, 152, 46, 18, 196, 115, 233, 149, 205, 189, 10, 232, 174, + 21, 2, 52, 202, 111, 74, 160, 191, 196, 84, 93, 98, 46, + ]), + Bytes32([ + 201, 148, 124, 172, 62, 154, 127, 129, 205, 197, 134, 133, 144, 78, 47, 190, 197, 190, 103, + 44, 129, 57, 155, 227, 152, 212, 130, 12, 192, 223, 244, 68, + ]), + Bytes32([ + 102, 147, 19, 104, 237, 188, 140, 66, 166, 77, 105, 55, 5, 165, 143, 107, 91, 247, 53, 203, + 187, 163, 109, 66, 19, 164, 153, 170, 82, 251, 148, 10, + ]), + Bytes32([ + 33, 89, 246, 96, 201, 15, 77, 99, 252, 111, 250, 152, 124, 80, 50, 57, 197, 124, 254, 202, + 246, 131, 11, 219, 249, 102, 35, 79, 100, 173, 146, 167, + ]), + Bytes32([ + 6, 27, 205, 165, 249, 112, 70, 105, 232, 156, 155, 204, 71, 5, 21, 239, 91, 69, 248, 111, + 218, 154, 187, 85, 118, 72, 210, 99, 138, 40, 233, 75, + ]), +]; + +const MODULE_HASHES: &[Bytes32; 64] = &[ + Bytes32([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + ]), + Bytes32([ + 252, 178, 61, 5, 174, 66, 106, 30, 131, 163, 114, 90, 231, 83, 228, 153, 108, 255, 60, 37, + 254, 139, 153, 129, 208, 156, 109, 74, 233, 129, 174, 182, + ]), + Bytes32([ + 128, 23, 154, 62, 181, 220, 154, 183, 222, 214, 79, 76, 162, 169, 179, 162, 185, 93, 179, + 115, 161, 55, 19, 63, 227, 168, 140, 66, 182, 6, 60, 120, + ]), + Bytes32([ + 243, 119, 126, 55, 151, 128, 119, 12, 124, 84, 146, 243, 156, 68, 82, 174, 201, 162, 29, + 73, 29, 77, 103, 205, 194, 250, 45, 133, 39, 71, 224, 177, + ]), + Bytes32([ + 209, 179, 222, 187, 184, 84, 131, 182, 172, 78, 20, 104, 236, 246, 114, 74, 55, 98, 29, 34, + 117, 249, 89, 76, 85, 38, 248, 193, 75, 10, 243, 100, + ]), + Bytes32([ + 195, 14, 58, 139, 148, 140, 218, 174, 131, 204, 69, 84, 127, 8, 142, 88, 136, 83, 253, 241, + 74, 247, 143, 204, 38, 15, 138, 98, 47, 188, 255, 245, + ]), + Bytes32([ + 167, 4, 177, 126, 159, 76, 19, 220, 160, 159, 81, 227, 110, 147, 179, 175, 253, 187, 46, + 24, 15, 168, 153, 84, 4, 167, 247, 225, 121, 175, 134, 85, + ]), + Bytes32([ + 237, 144, 152, 155, 211, 100, 202, 187, 41, 181, 45, 224, 143, 139, 18, 77, 110, 34, 212, + 207, 239, 180, 73, 84, 166, 194, 22, 149, 89, 215, 86, 21, + ]), + Bytes32([ + 226, 192, 91, 176, 242, 185, 212, 189, 178, 80, 238, 252, 183, 82, 220, 242, 22, 237, 84, + 142, 132, 91, 95, 219, 252, 171, 51, 76, 28, 146, 86, 155, + ]), + Bytes32([ + 199, 200, 237, 66, 220, 14, 221, 121, 117, 150, 118, 36, 138, 142, 50, 173, 12, 195, 131, + 90, 27, 189, 247, 221, 89, 151, 41, 27, 135, 207, 137, 172, + ]), + Bytes32([ + 160, 60, 124, 200, 56, 240, 67, 161, 121, 95, 247, 51, 153, 249, 125, 88, 231, 2, 85, 167, + 251, 187, 21, 103, 49, 132, 213, 52, 219, 30, 146, 59, + ]), + Bytes32([ + 123, 52, 142, 254, 117, 160, 215, 99, 155, 130, 134, 183, 76, 99, 166, 246, 49, 51, 142, + 67, 116, 234, 69, 199, 201, 19, 70, 3, 208, 247, 40, 82, + ]), + Bytes32([ + 165, 32, 183, 79, 246, 224, 220, 103, 11, 160, 233, 66, 129, 238, 194, 73, 17, 37, 128, + 185, 175, 88, 144, 228, 231, 185, 22, 17, 149, 174, 72, 1, + ]), + Bytes32([ + 12, 24, 45, 128, 57, 246, 187, 176, 154, 247, 169, 18, 116, 176, 70, 246, 203, 141, 211, + 104, 5, 147, 78, 214, 161, 71, 33, 97, 7, 21, 158, 61, + ]), + Bytes32([ + 215, 18, 110, 29, 36, 34, 133, 219, 15, 204, 206, 158, 186, 213, 181, 41, 184, 160, 71, + 165, 163, 121, 88, 106, 228, 58, 34, 105, 112, 168, 84, 123, + ]), + Bytes32([ + 6, 169, 156, 220, 55, 53, 26, 229, 104, 60, 113, 111, 153, 18, 251, 234, 179, 159, 56, 14, + 112, 7, 144, 199, 45, 180, 116, 239, 21, 207, 173, 205, + ]), + Bytes32([ + 24, 172, 76, 192, 21, 91, 250, 75, 196, 119, 231, 221, 13, 239, 113, 39, 62, 40, 165, 26, + 245, 16, 61, 106, 39, 28, 78, 212, 249, 230, 84, 108, + ]), + Bytes32([ + 248, 34, 1, 62, 213, 235, 20, 21, 220, 78, 178, 126, 184, 102, 242, 50, 49, 174, 163, 122, + 166, 96, 40, 110, 78, 199, 89, 158, 155, 251, 233, 49, + ]), + Bytes32([ + 103, 54, 133, 19, 189, 117, 46, 209, 17, 2, 64, 251, 77, 195, 197, 91, 38, 48, 214, 36, 96, + 255, 133, 87, 244, 101, 166, 218, 167, 129, 225, 167, + ]), + Bytes32([ + 196, 159, 226, 85, 100, 246, 179, 251, 133, 33, 114, 51, 104, 245, 81, 54, 137, 126, 245, + 76, 112, 146, 139, 185, 190, 19, 106, 132, 48, 203, 34, 237, + ]), + Bytes32([ + 41, 190, 7, 23, 227, 80, 13, 134, 244, 18, 215, 148, 1, 72, 1, 22, 91, 165, 182, 69, 160, + 179, 241, 106, 254, 116, 245, 131, 136, 35, 190, 226, + ]), + Bytes32([ + 205, 132, 211, 121, 67, 210, 191, 102, 218, 92, 56, 204, 68, 160, 188, 100, 229, 80, 77, + 27, 26, 86, 248, 86, 216, 39, 242, 211, 183, 139, 219, 83, + ]), + Bytes32([ + 13, 215, 68, 100, 180, 74, 23, 58, 157, 140, 76, 31, 114, 254, 85, 78, 234, 40, 251, 199, + 35, 204, 111, 243, 163, 64, 221, 21, 96, 55, 127, 118, + ]), + Bytes32([ + 225, 14, 246, 105, 64, 96, 225, 200, 186, 66, 40, 253, 131, 80, 102, 178, 83, 22, 150, 32, + 15, 139, 76, 172, 144, 3, 30, 43, 217, 213, 89, 43, + ]), + Bytes32([ + 200, 83, 93, 27, 98, 246, 87, 100, 53, 166, 89, 138, 157, 88, 148, 245, 61, 115, 246, 20, + 142, 156, 54, 237, 179, 64, 148, 218, 67, 5, 142, 248, + ]), + Bytes32([ + 159, 25, 150, 25, 114, 252, 162, 57, 21, 125, 147, 111, 220, 117, 17, 107, 40, 21, 157, + 183, 6, 63, 226, 37, 64, 179, 133, 58, 107, 245, 78, 14, + ]), + Bytes32([ + 58, 243, 16, 193, 174, 42, 255, 46, 40, 128, 26, 167, 173, 164, 71, 226, 155, 205, 26, 127, + 154, 24, 74, 244, 106, 251, 25, 221, 197, 176, 194, 17, + ]), + Bytes32([ + 51, 47, 251, 206, 27, 9, 142, 27, 253, 132, 189, 62, 109, 150, 246, 2, 137, 90, 157, 185, + 59, 96, 0, 154, 29, 17, 231, 3, 84, 95, 49, 51, + ]), + Bytes32([ + 250, 158, 158, 248, 206, 150, 95, 254, 53, 140, 80, 102, 67, 26, 76, 127, 236, 86, 182, + 120, 72, 239, 190, 118, 60, 77, 28, 82, 152, 234, 73, 201, + ]), + Bytes32([ + 255, 137, 155, 144, 74, 231, 231, 43, 187, 202, 137, 66, 205, 37, 40, 225, 0, 33, 87, 137, + 113, 163, 58, 64, 147, 74, 123, 128, 19, 156, 46, 83, + ]), + Bytes32([ + 207, 61, 79, 4, 202, 96, 238, 144, 154, 230, 145, 65, 230, 130, 246, 10, 140, 71, 66, 246, + 53, 230, 148, 1, 248, 103, 145, 149, 157, 38, 169, 8, + ]), + Bytes32([ + 33, 168, 110, 82, 84, 151, 70, 98, 115, 2, 221, 116, 210, 10, 247, 189, 203, 245, 186, 86, + 121, 142, 218, 95, 68, 241, 21, 219, 131, 241, 185, 203, + ]), + Bytes32([ + 125, 247, 7, 149, 181, 71, 68, 141, 123, 207, 144, 83, 170, 27, 244, 37, 210, 148, 0, 140, + 144, 159, 237, 216, 227, 247, 85, 229, 80, 174, 40, 48, + ]), + Bytes32([ + 0, 205, 68, 89, 77, 97, 204, 140, 113, 244, 168, 76, 49, 137, 236, 21, 132, 99, 10, 206, + 195, 206, 208, 120, 227, 77, 21, 223, 145, 227, 48, 139, + ]), + Bytes32([ + 10, 153, 106, 155, 149, 65, 211, 247, 246, 5, 129, 126, 74, 14, 113, 168, 152, 154, 205, + 139, 49, 2, 182, 65, 163, 15, 62, 126, 62, 16, 26, 36, + ]), + Bytes32([ + 24, 251, 204, 187, 179, 146, 114, 66, 110, 182, 131, 248, 36, 170, 169, 128, 22, 221, 134, + 193, 121, 189, 128, 94, 83, 255, 226, 37, 133, 83, 220, 181, + ]), + Bytes32([ + 25, 52, 245, 155, 53, 39, 73, 130, 12, 73, 106, 255, 44, 204, 208, 41, 32, 126, 159, 98, + 197, 67, 58, 90, 6, 146, 25, 166, 195, 194, 215, 70, + ]), + Bytes32([ + 194, 167, 206, 222, 96, 6, 86, 241, 95, 105, 225, 147, 99, 93, 201, 220, 166, 145, 4, 25, + 168, 188, 21, 168, 80, 163, 132, 216, 239, 19, 115, 36, + ]), + Bytes32([ + 243, 16, 4, 9, 140, 42, 62, 105, 97, 7, 4, 234, 200, 227, 42, 10, 51, 167, 38, 148, 69, + 154, 143, 179, 94, 177, 248, 28, 33, 61, 166, 187, + ]), + Bytes32([ + 156, 201, 97, 197, 223, 83, 229, 186, 187, 33, 49, 210, 181, 222, 180, 234, 150, 33, 99, + 168, 157, 26, 241, 1, 213, 220, 165, 8, 31, 76, 134, 243, + ]), + Bytes32([ + 34, 218, 29, 74, 212, 218, 95, 6, 53, 10, 63, 174, 119, 90, 90, 35, 92, 124, 169, 222, 75, + 61, 199, 118, 132, 40, 193, 9, 250, 80, 12, 197, + ]), + Bytes32([ + 102, 137, 75, 155, 181, 222, 86, 192, 140, 167, 3, 178, 212, 165, 49, 163, 86, 8, 76, 240, + 32, 202, 34, 159, 217, 173, 101, 125, 237, 34, 48, 179, + ]), + Bytes32([ + 136, 53, 156, 19, 107, 234, 210, 218, 180, 236, 9, 7, 80, 63, 146, 57, 77, 106, 135, 64, + 23, 184, 9, 139, 61, 237, 225, 157, 183, 182, 137, 31, + ]), + Bytes32([ + 237, 226, 115, 218, 228, 122, 45, 46, 67, 21, 130, 204, 80, 2, 28, 47, 148, 191, 28, 33, + 177, 47, 207, 14, 33, 117, 28, 46, 88, 254, 97, 227, + ]), + Bytes32([ + 38, 87, 252, 28, 105, 20, 117, 29, 234, 237, 60, 91, 48, 101, 219, 219, 24, 52, 169, 243, + 71, 214, 117, 41, 207, 17, 148, 77, 218, 44, 122, 167, + ]), + Bytes32([ + 235, 31, 185, 222, 3, 22, 222, 174, 126, 128, 55, 67, 201, 229, 55, 28, 241, 144, 184, 85, + 141, 153, 183, 211, 66, 80, 152, 248, 214, 130, 64, 205, + ]), + Bytes32([ + 52, 169, 226, 179, 195, 44, 245, 101, 35, 92, 145, 174, 152, 212, 192, 148, 241, 72, 248, + 61, 239, 124, 98, 213, 181, 75, 84, 121, 57, 90, 172, 164, + ]), + Bytes32([ + 27, 19, 12, 74, 128, 193, 65, 63, 15, 6, 174, 167, 79, 56, 88, 13, 117, 6, 189, 14, 11, 13, + 133, 136, 141, 64, 74, 17, 159, 192, 251, 242, + ]), + Bytes32([ + 101, 69, 132, 221, 127, 162, 162, 92, 248, 131, 39, 52, 169, 170, 231, 137, 123, 106, 161, + 16, 202, 242, 216, 245, 211, 170, 74, 128, 108, 243, 166, 38, + ]), + Bytes32([ + 157, 82, 193, 234, 117, 199, 118, 245, 63, 31, 186, 32, 135, 233, 29, 213, 217, 119, 208, + 64, 149, 116, 117, 129, 211, 225, 207, 22, 225, 99, 194, 222, + ]), + Bytes32([ + 112, 194, 64, 229, 154, 223, 109, 8, 191, 120, 32, 176, 154, 7, 174, 103, 2, 156, 230, 164, + 245, 252, 0, 116, 213, 40, 20, 239, 135, 62, 198, 42, + ]), + Bytes32([ + 32, 91, 5, 170, 221, 134, 167, 144, 16, 130, 237, 114, 71, 184, 131, 223, 92, 149, 161, 68, + 196, 56, 73, 148, 203, 187, 174, 178, 178, 53, 156, 177, + ]), + Bytes32([ + 234, 97, 64, 211, 81, 59, 14, 249, 38, 8, 247, 37, 243, 37, 88, 234, 19, 54, 146, 63, 88, + 79, 127, 190, 144, 51, 240, 19, 15, 143, 18, 9, + ]), + Bytes32([ + 247, 102, 43, 28, 24, 201, 189, 198, 66, 58, 210, 51, 174, 234, 52, 239, 37, 83, 212, 184, + 127, 170, 168, 127, 47, 11, 248, 213, 84, 3, 201, 181, + ]), + Bytes32([ + 126, 18, 116, 33, 129, 25, 247, 2, 162, 202, 103, 201, 237, 67, 28, 80, 46, 182, 163, 239, + 90, 204, 47, 196, 137, 79, 19, 165, 209, 84, 140, 132, + ]), + Bytes32([ + 189, 160, 148, 101, 82, 248, 215, 206, 90, 91, 205, 148, 37, 38, 172, 82, 223, 228, 66, + 173, 220, 246, 194, 73, 231, 17, 220, 47, 222, 175, 7, 24, + ]), + Bytes32([ + 237, 149, 54, 210, 99, 72, 182, 55, 69, 140, 161, 215, 104, 90, 104, 26, 216, 241, 232, + 210, 37, 77, 56, 216, 6, 160, 199, 247, 164, 227, 142, 255, + ]), + Bytes32([ + 11, 57, 131, 77, 203, 89, 156, 126, 200, 215, 103, 209, 70, 235, 78, 247, 0, 126, 209, 248, + 220, 135, 158, 244, 141, 74, 6, 158, 19, 37, 42, 39, + ]), + Bytes32([ + 107, 131, 231, 102, 64, 182, 78, 253, 77, 143, 94, 34, 199, 93, 44, 131, 169, 211, 71, 223, + 53, 230, 59, 107, 146, 22, 188, 207, 210, 220, 168, 129, + ]), + Bytes32([ + 78, 71, 246, 216, 154, 188, 152, 6, 234, 254, 21, 1, 128, 148, 56, 91, 250, 95, 76, 103, + 15, 250, 137, 186, 114, 254, 122, 69, 208, 242, 69, 111, + ]), + Bytes32([ + 82, 241, 242, 155, 248, 109, 84, 118, 225, 255, 122, 40, 3, 87, 20, 223, 212, 205, 141, + 178, 32, 229, 234, 146, 101, 73, 79, 55, 28, 82, 81, 178, + ]), + Bytes32([ + 35, 169, 243, 198, 215, 220, 113, 91, 6, 79, 48, 201, 97, 143, 212, 34, 247, 46, 38, 93, + 166, 213, 158, 218, 61, 86, 240, 149, 224, 174, 225, 73, + ]), + Bytes32([ + 25, 108, 21, 212, 193, 192, 96, 39, 57, 72, 193, 99, 239, 0, 231, 83, 183, 195, 105, 33, + 220, 187, 18, 148, 43, 30, 42, 127, 192, 240, 13, 224, + ]), + Bytes32([ + 119, 117, 186, 31, 43, 128, 143, 25, 182, 135, 156, 58, 152, 81, 70, 116, 171, 137, 125, + 157, 152, 163, 34, 65, 240, 178, 12, 24, 168, 111, 39, 35, + ]), +]; + +pub const EMPTY_HASH: &Bytes32 = &Bytes32([0; 32]); + +pub const ZERO_HASHES: &[&[Bytes32; 64]; 7] = &[ + VALUE_HASHES, + FUNCTION_HASHES, + INSTRUCTION_HASHES, + MEMORY_HASHES, + TABLE_HASHES, + TABLE_ELEMENT_HASHES, + MODULE_HASHES, +]; diff --git a/arbitrator/stylus/src/test/mod.rs b/arbitrator/stylus/src/test/mod.rs index d7f3248d31..236e5639e6 100644 --- a/arbitrator/stylus/src/test/mod.rs +++ b/arbitrator/stylus/src/test/mod.rs @@ -150,7 +150,6 @@ fn new_test_machine(path: &str, compile: &CompileConfig) -> Result { &[lib], bin, false, - false, true, compile.debug.debug_funcs, true, diff --git a/arbitrator/wasm-libraries/Cargo.lock b/arbitrator/wasm-libraries/Cargo.lock index bea50f6592..88525ececa 100644 --- a/arbitrator/wasm-libraries/Cargo.lock +++ b/arbitrator/wasm-libraries/Cargo.lock @@ -120,6 +120,7 @@ checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", + "serde", "tap", "wyz", ] @@ -384,7 +385,16 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6" dependencies = [ - "enum-iterator-derive", + "enum-iterator-derive 0.7.0", +] + +[[package]] +name = "enum-iterator" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e0b48d2b80ff6b002339547442496ea29d66a8c66ce8e1a6bd8c58b9cec7cf3" +dependencies = [ + "enum-iterator-derive 1.3.1", ] [[package]] @@ -398,6 +408,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "enum-iterator-derive" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19cbb53d33b57ac4df1f0af6b92c38c107cded663c4aea9fae1189dcfc17cf5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "enumset" version = "1.1.3" @@ -865,9 +886,11 @@ version = "0.1.0" dependencies = [ "arbutil", "bincode", + "bitvec", "brotli", "derivative", "digest 0.9.0", + "enum-iterator 2.0.1", "eyre", "fnv", "hex", @@ -1437,7 +1460,7 @@ name = "wasmer-types" version = "4.2.8" dependencies = [ "bytecheck", - "enum-iterator", + "enum-iterator 0.7.0", "enumset", "indexmap 1.9.3", "more-asserts", diff --git a/arbnode/inbox_test.go b/arbnode/inbox_test.go index ef4acd038c..70392598d6 100644 --- a/arbnode/inbox_test.go +++ b/arbnode/inbox_test.go @@ -19,6 +19,7 @@ import ( "github.com/offchainlabs/nitro/util/arbmath" "github.com/offchainlabs/nitro/util/testhelpers" + "github.com/offchainlabs/nitro/util/testhelpers/env" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" @@ -59,7 +60,8 @@ func NewTransactionStreamerForTest(t *testing.T, ownerAddress common.Address) (* arbDb := rawdb.NewMemoryDatabase() initReader := statetransfer.NewMemoryInitDataReader(&initData) - bc, err := gethexec.WriteOrTestBlockChain(chainDb, nil, initReader, chainConfig, arbostypes.TestInitMessage, gethexec.ConfigDefaultTest().TxLookupLimit, 0) + cacheConfig := core.DefaultCacheConfigWithScheme(env.GetTestStateScheme()) + bc, err := gethexec.WriteOrTestBlockChain(chainDb, cacheConfig, initReader, chainConfig, arbostypes.TestInitMessage, gethexec.ConfigDefault.TxLookupLimit, 0) if err != nil { Fail(t, err) diff --git a/arbnode/node.go b/arbnode/node.go index a2ccdd1834..ac18a6c7d4 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -779,7 +779,7 @@ func CreateNode( } if currentNode.StatelessBlockValidator != nil { apis = append(apis, rpc.API{ - Namespace: "arbvalidator", + Namespace: "arbdebug", Version: "1.0", Service: &BlockValidatorDebugAPI{ val: currentNode.StatelessBlockValidator, diff --git a/arbos/arbosState/arbosstate.go b/arbos/arbosState/arbosstate.go index 9ff3dd3aa5..91c2207aae 100644 --- a/arbos/arbosState/arbosstate.go +++ b/arbos/arbosState/arbosstate.go @@ -15,6 +15,9 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/triedb" + "github.com/ethereum/go-ethereum/triedb/hashdb" + "github.com/ethereum/go-ethereum/triedb/pathdb" "github.com/offchainlabs/nitro/arbcompress" "github.com/offchainlabs/nitro/arbos/addressSet" @@ -29,6 +32,7 @@ import ( "github.com/offchainlabs/nitro/arbos/retryables" "github.com/offchainlabs/nitro/arbos/storage" "github.com/offchainlabs/nitro/arbos/util" + "github.com/offchainlabs/nitro/util/testhelpers/env" ) // ArbosState contains ArbOS-related state. It is backed by ArbOS's storage in the persistent stateDB. @@ -115,7 +119,11 @@ func OpenSystemArbosStateOrPanic(stateDB vm.StateDB, tracingInfo *util.TracingIn // NewArbosMemoryBackedArbOSState creates and initializes a memory-backed ArbOS state (for testing only) func NewArbosMemoryBackedArbOSState() (*ArbosState, *state.StateDB) { raw := rawdb.NewMemoryDatabase() - db := state.NewDatabase(raw) + trieConfig := &triedb.Config{Preimages: false, PathDB: pathdb.Defaults} + if env.GetTestStateScheme() == rawdb.HashScheme { + trieConfig = &triedb.Config{Preimages: false, HashDB: hashdb.Defaults} + } + db := state.NewDatabaseWithConfig(raw, trieConfig) statedb, err := state.New(common.Hash{}, db, nil) if err != nil { log.Crit("failed to init empty statedb", "error", err) diff --git a/arbos/arbosState/initialization_test.go b/arbos/arbosState/initialization_test.go index 0ef9cea4c5..34802392fe 100644 --- a/arbos/arbosState/initialization_test.go +++ b/arbos/arbosState/initialization_test.go @@ -10,6 +10,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/params" @@ -17,6 +18,7 @@ import ( "github.com/offchainlabs/nitro/arbos/burn" "github.com/offchainlabs/nitro/statetransfer" "github.com/offchainlabs/nitro/util/testhelpers" + "github.com/offchainlabs/nitro/util/testhelpers/env" ) func TestJsonMarshalUnmarshal(t *testing.T) { @@ -60,10 +62,13 @@ func tryMarshalUnmarshal(input *statetransfer.ArbosInitializationInfo, t *testin initReader := statetransfer.NewMemoryInitDataReader(&initData) chainConfig := params.ArbitrumDevTestChainConfig() - stateroot, err := InitializeArbosInDatabase(raw, initReader, chainConfig, arbostypes.TestInitMessage, 0, 0) + + cacheConfig := core.DefaultCacheConfigWithScheme(env.GetTestStateScheme()) + stateroot, err := InitializeArbosInDatabase(raw, cacheConfig, initReader, chainConfig, arbostypes.TestInitMessage, 0, 0) Require(t, err) - stateDb, err := state.New(stateroot, state.NewDatabase(raw), nil) + triedbConfig := cacheConfig.TriedbConfig() + stateDb, err := state.New(stateroot, state.NewDatabaseWithConfig(raw, triedbConfig), nil) Require(t, err) arbState, err := OpenArbosState(stateDb, &burn.SystemBurner{}) diff --git a/arbos/arbosState/initialize.go b/arbos/arbosState/initialize.go index 796f959c73..3ccc4d3d96 100644 --- a/arbos/arbosState/initialize.go +++ b/arbos/arbosState/initialize.go @@ -10,6 +10,7 @@ import ( "sort" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethdb" @@ -52,13 +53,20 @@ func MakeGenesisBlock(parentHash common.Hash, blockNumber uint64, timestamp uint return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)) } -func InitializeArbosInDatabase(db ethdb.Database, initData statetransfer.InitDataReader, chainConfig *params.ChainConfig, initMessage *arbostypes.ParsedInitMessage, timestamp uint64, accountsPerSync uint) (common.Hash, error) { - stateDatabase := state.NewDatabase(db) +func InitializeArbosInDatabase(db ethdb.Database, cacheConfig *core.CacheConfig, initData statetransfer.InitDataReader, chainConfig *params.ChainConfig, initMessage *arbostypes.ParsedInitMessage, timestamp uint64, accountsPerSync uint) (root common.Hash, err error) { + triedbConfig := cacheConfig.TriedbConfig() + triedbConfig.Preimages = false + stateDatabase := state.NewDatabaseWithConfig(db, triedbConfig) + defer func() { + err = errors.Join(err, stateDatabase.TrieDB().Close()) + }() statedb, err := state.New(common.Hash{}, stateDatabase, nil) if err != nil { log.Crit("failed to init empty statedb", "error", err) } + // commit avoids keeping the entire state in memory while importing the state. + // At some time it was also used to avoid reprocessing the whole import in case of a crash. commit := func() (common.Hash, error) { root, err := statedb.Commit(chainConfig.ArbitrumChainParams.GenesisBlockNum, true) if err != nil { diff --git a/arbos/storage/storage.go b/arbos/storage/storage.go index 158b8896c1..6e6c976644 100644 --- a/arbos/storage/storage.go +++ b/arbos/storage/storage.go @@ -18,9 +18,13 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/triedb" + "github.com/ethereum/go-ethereum/triedb/hashdb" + "github.com/ethereum/go-ethereum/triedb/pathdb" "github.com/offchainlabs/nitro/arbos/burn" "github.com/offchainlabs/nitro/arbos/util" "github.com/offchainlabs/nitro/util/arbmath" + "github.com/offchainlabs/nitro/util/testhelpers/env" ) // Storage allows ArbOS to store data persistently in the Ethereum-compatible stateDB. This is represented in @@ -73,15 +77,21 @@ func NewGeth(statedb vm.StateDB, burner burn.Burner) *Storage { } } -// NewMemoryBacked uses Geth's memory-backed database to create an evm key-value store +// NewMemoryBacked uses Geth's memory-backed database to create an evm key-value store. +// Only used for testing. func NewMemoryBacked(burner burn.Burner) *Storage { return NewGeth(NewMemoryBackedStateDB(), burner) } // NewMemoryBackedStateDB uses Geth's memory-backed database to create a statedb +// Only used for testing. func NewMemoryBackedStateDB() vm.StateDB { raw := rawdb.NewMemoryDatabase() - db := state.NewDatabase(raw) + trieConfig := &triedb.Config{Preimages: false, PathDB: pathdb.Defaults} + if env.GetTestStateScheme() == rawdb.HashScheme { + trieConfig = &triedb.Config{Preimages: false, HashDB: hashdb.Defaults} + } + db := state.NewDatabaseWithConfig(raw, trieConfig) statedb, err := state.New(common.Hash{}, db, nil) if err != nil { panic("failed to init empty statedb") diff --git a/cmd/nitro/config_test.go b/cmd/nitro/config_test.go index f94f941e0b..33feac887b 100644 --- a/cmd/nitro/config_test.go +++ b/cmd/nitro/config_test.go @@ -53,12 +53,31 @@ func TestUnsafeStakerConfig(t *testing.T) { Require(t, err) } +const validatorArgs = "--persistent.chain /tmp/data --init.dev-init --node.parent-chain-reader.enable=false --parent-chain.id 5 --chain.id 421613 --node.staker.parent-chain-wallet.pathname /l1keystore --node.staker.parent-chain-wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.staker.enable --node.staker.strategy MakeNodes --node.staker.staker-interval 10s --execution.forwarding-target null" + func TestValidatorConfig(t *testing.T) { args := strings.Split("--persistent.chain /tmp/data --init.dev-init --node.parent-chain-reader.enable=false --parent-chain.id 5 --chain.id 421613 --node.staker.parent-chain-wallet.pathname /l1keystore --node.staker.parent-chain-wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.staker.enable --node.staker.strategy MakeNodes --node.staker.staker-interval 10s --execution.forwarding-target null", " ") _, _, err := ParseNode(context.Background(), args) Require(t, err) } +func TestInvalidCachingStateSchemeForValidator(t *testing.T) { + validatorArgsWithPathScheme := fmt.Sprintf("%s --execution.caching.state-scheme path", validatorArgs) + args := strings.Split(validatorArgsWithPathScheme, " ") + _, _, err := ParseNode(context.Background(), args) + if !strings.Contains(err.Error(), "path cannot be used as execution.caching.state-scheme when validator is required") { + Fail(t, "failed to detect invalid state scheme for validator") + } +} + +func TestInvalidArchiveConfig(t *testing.T) { + args := strings.Split("--execution.caching.archive --execution.caching.state-scheme path --persistent.chain /tmp/data --init.dev-init --node.parent-chain-reader.enable=false --parent-chain.id 5 --chain.id 421613 --node.staker.parent-chain-wallet.pathname /l1keystore --node.staker.parent-chain-wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.staker.enable --node.staker.strategy MakeNodes --node.staker.staker-interval 10s --execution.forwarding-target null", " ") + _, _, err := ParseNode(context.Background(), args) + if !strings.Contains(err.Error(), "archive cannot be set when using path as the state-scheme") { + Fail(t, "failed to detect invalid state scheme for archive") + } +} + func TestAggregatorConfig(t *testing.T) { args := strings.Split("--persistent.chain /tmp/data --init.dev-init --node.parent-chain-reader.enable=false --parent-chain.id 5 --chain.id 421613 --node.batch-poster.parent-chain-wallet.pathname /l1keystore --node.batch-poster.parent-chain-wallet.password passphrase --http.addr 0.0.0.0 --ws.addr 0.0.0.0 --node.sequencer --execution.sequencer.enable --node.feed.output.enable --node.feed.output.port 9642 --node.data-availability.enable --node.data-availability.rpc-aggregator.backends [{\"url\":\"http://localhost:8547\",\"pubkey\":\"abc==\"}]", " ") _, _, err := ParseNode(context.Background(), args) diff --git a/cmd/nitro/init.go b/cmd/nitro/init.go index ea48ec8784..a958572458 100644 --- a/cmd/nitro/init.go +++ b/cmd/nitro/init.go @@ -423,6 +423,10 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo return nil, nil, err } chainDb := rawdb.WrapDatabaseWithWasm(chainData, wasmDb, 1) + _, err = rawdb.ParseStateScheme(cacheConfig.StateScheme, chainDb) + if err != nil { + return nil, nil, err + } err = pruning.PruneChainDb(ctx, chainDb, stack, &config.Init, cacheConfig, persistentConfig, l1Client, rollupAddrs, config.Node.ValidatorRequired()) if err != nil { return chainDb, nil, fmt.Errorf("error pruning: %w", err) @@ -533,6 +537,10 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo return nil, nil, err } chainDb := rawdb.WrapDatabaseWithWasm(chainData, wasmDb, 1) + _, err = rawdb.ParseStateScheme(cacheConfig.StateScheme, chainDb) + if err != nil { + return nil, nil, err + } // Rebuilding wasm store is not required when just starting out err = gethexec.WriteToKeyValueStore(wasmDb, gethexec.RebuildingPositionKey, gethexec.RebuildingDone) @@ -673,6 +681,10 @@ func openInitializeChainDb(ctx context.Context, stack *node.Node, config *NodeCo log.Warn("Created fake init message as L1Reader is disabled and serialized chain config from init message is not available", "json", string(serializedChainConfig)) } + emptyBlockChain := rawdb.ReadHeadHeader(chainDb) == nil + if !emptyBlockChain && (cacheConfig.StateScheme == rawdb.PathScheme) && config.Init.Force { + return chainDb, nil, errors.New("It is not possible to force init with non-empty blockchain when using path scheme") + } l2BlockChain, err = gethexec.WriteOrTestBlockChain(chainDb, cacheConfig, initDataReader, chainConfig, parsedInitMessage, config.Execution.TxLookupLimit, config.Init.AccountsPerSync) if err != nil { return chainDb, nil, err diff --git a/cmd/nitro/init_test.go b/cmd/nitro/init_test.go index 6c363972e9..0797ac9b46 100644 --- a/cmd/nitro/init_test.go +++ b/cmd/nitro/init_test.go @@ -1,4 +1,4 @@ -// Copyright 2021-2022, Offchain Labs, Inc. +// Copyright 2021-2024, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE package main @@ -10,6 +10,7 @@ import ( "encoding/hex" "errors" "fmt" + "math/big" "net" "net/http" "os" @@ -19,8 +20,13 @@ import ( "testing" "time" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/node" + "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/cmd/chaininfo" "github.com/offchainlabs/nitro/cmd/conf" + "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/util/testhelpers" ) @@ -361,3 +367,72 @@ func TestEmptyDatabaseDir(t *testing.T) { }) } } + +func TestOpenInitializeChainDbIncompatibleStateScheme(t *testing.T) { + t.Parallel() + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + stackConfig := testhelpers.CreateStackConfigForTest(t.TempDir()) + stack, err := node.New(stackConfig) + defer stack.Close() + Require(t, err) + + nodeConfig := NodeConfigDefault + nodeConfig.Execution.Caching.StateScheme = rawdb.PathScheme + nodeConfig.Chain.ID = 42161 + nodeConfig.Node = *arbnode.ConfigDefaultL2Test() + nodeConfig.Init.DevInit = true + nodeConfig.Init.DevInitAddress = "0x3f1Eae7D46d88F08fc2F8ed27FCb2AB183EB2d0E" + + l1Client := ethclient.NewClient(stack.Attach()) + + // opening for the first time doesn't error + chainDb, blockchain, err := openInitializeChainDb( + ctx, + stack, + &nodeConfig, + new(big.Int).SetUint64(nodeConfig.Chain.ID), + gethexec.DefaultCacheConfigFor(stack, &nodeConfig.Execution.Caching), + &nodeConfig.Persistent, + l1Client, + chaininfo.RollupAddresses{}, + ) + Require(t, err) + blockchain.Stop() + err = chainDb.Close() + Require(t, err) + + // opening for the second time doesn't error + chainDb, blockchain, err = openInitializeChainDb( + ctx, + stack, + &nodeConfig, + new(big.Int).SetUint64(nodeConfig.Chain.ID), + gethexec.DefaultCacheConfigFor(stack, &nodeConfig.Execution.Caching), + &nodeConfig.Persistent, + l1Client, + chaininfo.RollupAddresses{}, + ) + Require(t, err) + blockchain.Stop() + err = chainDb.Close() + Require(t, err) + + // opening with a different state scheme errors + nodeConfig.Execution.Caching.StateScheme = rawdb.HashScheme + _, _, err = openInitializeChainDb( + ctx, + stack, + &nodeConfig, + new(big.Int).SetUint64(nodeConfig.Chain.ID), + gethexec.DefaultCacheConfigFor(stack, &nodeConfig.Execution.Caching), + &nodeConfig.Persistent, + l1Client, + chaininfo.RollupAddresses{}, + ) + if !strings.Contains(err.Error(), "incompatible state scheme, stored: path, provided: hash") { + t.Fatalf("Failed to detect incompatible state scheme") + } +} diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 3a34229768..9861bb673e 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -30,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/arbitrum" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" _ "github.com/ethereum/go-ethereum/eth/tracers/js" @@ -836,6 +837,9 @@ func (c *NodeConfig) Validate() error { if err := c.BlocksReExecutor.Validate(); err != nil { return err } + if c.Node.ValidatorRequired() && (c.Execution.Caching.StateScheme == rawdb.PathScheme) { + return errors.New("path cannot be used as execution.caching.state-scheme when validator is required") + } return c.Persistent.Validate() } diff --git a/cmd/pruning/pruning.go b/cmd/pruning/pruning.go index ab6ec80942..096bb4b1ae 100644 --- a/cmd/pruning/pruning.go +++ b/cmd/pruning/pruning.go @@ -233,6 +233,10 @@ func findImportantRoots(ctx context.Context, chainDb ethdb.Database, stack *node } func PruneChainDb(ctx context.Context, chainDb ethdb.Database, stack *node.Node, initConfig *conf.InitConfig, cacheConfig *core.CacheConfig, persistentConfig *conf.PersistentConfig, l1Client arbutil.L1Interface, rollupAddrs chaininfo.RollupAddresses, validatorRequired bool) error { + if cacheConfig.StateScheme == rawdb.PathScheme { + return nil + } + if initConfig.Prune == "" { return pruner.RecoverPruning(stack.InstanceDir(), chainDb, initConfig.PruneThreads) } diff --git a/cmd/staterecovery/staterecovery.go b/cmd/staterecovery/staterecovery.go index 19ed51ef2d..bb01477414 100644 --- a/cmd/staterecovery/staterecovery.go +++ b/cmd/staterecovery/staterecovery.go @@ -5,6 +5,7 @@ import ( "time" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethdb" @@ -30,12 +31,18 @@ func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheCon if previousBlock == nil { return fmt.Errorf("start block parent is missing, parent block number: %d", current-1) } + + if cacheConfig.StateScheme == rawdb.PathScheme { + return fmt.Errorf("recreating missing states, which is supposed to only run in archive mode, is not supported with path scheme") + } + hashConfig := *hashdb.Defaults hashConfig.CleanCacheSize = cacheConfig.TrieCleanLimit * 1024 * 1024 trieConfig := &triedb.Config{ Preimages: false, HashDB: &hashConfig, } + database := state.NewDatabaseWithConfig(chainDb, trieConfig) defer database.TrieDB().Close() previousState, err := state.New(previousBlock.Root(), database, nil) diff --git a/execution/gethexec/blockchain.go b/execution/gethexec/blockchain.go index 1d5060ca8a..996b87a9e6 100644 --- a/execution/gethexec/blockchain.go +++ b/execution/gethexec/blockchain.go @@ -38,6 +38,8 @@ type CachingConfig struct { MaxNumberOfBlocksToSkipStateSaving uint32 `koanf:"max-number-of-blocks-to-skip-state-saving"` MaxAmountOfGasToSkipStateSaving uint64 `koanf:"max-amount-of-gas-to-skip-state-saving"` StylusLRUCache uint32 `koanf:"stylus-lru-cache"` + StateScheme string `koanf:"state-scheme"` + StateHistory uint64 `koanf:"state-history"` } func CachingConfigAddOptions(prefix string, f *flag.FlagSet) { @@ -53,24 +55,15 @@ func CachingConfigAddOptions(prefix string, f *flag.FlagSet) { f.Uint32(prefix+".max-number-of-blocks-to-skip-state-saving", DefaultCachingConfig.MaxNumberOfBlocksToSkipStateSaving, "maximum number of blocks to skip state saving to persistent storage (archive node only) -- warning: this option seems to cause issues") f.Uint64(prefix+".max-amount-of-gas-to-skip-state-saving", DefaultCachingConfig.MaxAmountOfGasToSkipStateSaving, "maximum amount of gas in blocks to skip saving state to Persistent storage (archive node only) -- warning: this option seems to cause issues") f.Uint32(prefix+".stylus-lru-cache", DefaultCachingConfig.StylusLRUCache, "initialized stylus programs to keep in LRU cache") + f.String(prefix+".state-scheme", DefaultCachingConfig.StateScheme, "scheme to use for state trie storage (hash, path)") + f.Uint64(prefix+".state-history", DefaultCachingConfig.StateHistory, "number of recent blocks to retain state history for (path state-scheme only)") } -var DefaultCachingConfig = CachingConfig{ - Archive: false, - BlockCount: 128, - BlockAge: 30 * time.Minute, - TrieTimeLimit: time.Hour, - TrieDirtyCache: 1024, - TrieCleanCache: 600, - SnapshotCache: 400, - DatabaseCache: 2048, - SnapshotRestoreGasLimit: 300_000_000_000, - MaxNumberOfBlocksToSkipStateSaving: 0, - MaxAmountOfGasToSkipStateSaving: 0, - StylusLRUCache: 256, +func getStateHistory(maxBlockSpeed time.Duration) uint64 { + return uint64(24 * time.Hour / maxBlockSpeed) } -var TestCachingConfig = CachingConfig{ +var DefaultCachingConfig = CachingConfig{ Archive: false, BlockCount: 128, BlockAge: 30 * time.Minute, @@ -82,7 +75,9 @@ var TestCachingConfig = CachingConfig{ SnapshotRestoreGasLimit: 300_000_000_000, MaxNumberOfBlocksToSkipStateSaving: 0, MaxAmountOfGasToSkipStateSaving: 0, - StylusLRUCache: 0, + StylusLRUCache: 256, + StateScheme: rawdb.HashScheme, + StateHistory: getStateHistory(DefaultSequencerConfig.MaxBlockSpeed), } // TODO remove stack from parameters as it is no longer needed here @@ -105,10 +100,29 @@ func DefaultCacheConfigFor(stack *node.Node, cachingConfig *CachingConfig) *core SnapshotRestoreMaxGas: cachingConfig.SnapshotRestoreGasLimit, MaxNumberOfBlocksToSkipStateSaving: cachingConfig.MaxNumberOfBlocksToSkipStateSaving, MaxAmountOfGasToSkipStateSaving: cachingConfig.MaxAmountOfGasToSkipStateSaving, + StateScheme: cachingConfig.StateScheme, + StateHistory: cachingConfig.StateHistory, + } +} + +func (c *CachingConfig) validateStateScheme() error { + switch c.StateScheme { + case rawdb.HashScheme: + case rawdb.PathScheme: + if c.Archive { + return errors.New("archive cannot be set when using path as the state-scheme") + } + default: + return errors.New("Invalid StateScheme") } + return nil +} + +func (c *CachingConfig) Validate() error { + return c.validateStateScheme() } -func WriteOrTestGenblock(chainDb ethdb.Database, initData statetransfer.InitDataReader, chainConfig *params.ChainConfig, initMessage *arbostypes.ParsedInitMessage, accountsPerSync uint) error { +func WriteOrTestGenblock(chainDb ethdb.Database, cacheConfig *core.CacheConfig, initData statetransfer.InitDataReader, chainConfig *params.ChainConfig, initMessage *arbostypes.ParsedInitMessage, accountsPerSync uint) error { EmptyHash := common.Hash{} prevHash := EmptyHash prevDifficulty := big.NewInt(0) @@ -129,7 +143,7 @@ func WriteOrTestGenblock(chainDb ethdb.Database, initData statetransfer.InitData } timestamp = prevHeader.Time } - stateRoot, err := arbosState.InitializeArbosInDatabase(chainDb, initData, chainConfig, initMessage, timestamp, accountsPerSync) + stateRoot, err := arbosState.InitializeArbosInDatabase(chainDb, cacheConfig, initData, chainConfig, initMessage, timestamp, accountsPerSync) if err != nil { return err } @@ -197,7 +211,15 @@ func GetBlockChain(chainDb ethdb.Database, cacheConfig *core.CacheConfig, chainC } func WriteOrTestBlockChain(chainDb ethdb.Database, cacheConfig *core.CacheConfig, initData statetransfer.InitDataReader, chainConfig *params.ChainConfig, initMessage *arbostypes.ParsedInitMessage, txLookupLimit uint64, accountsPerSync uint) (*core.BlockChain, error) { - err := WriteOrTestGenblock(chainDb, initData, chainConfig, initMessage, accountsPerSync) + emptyBlockChain := rawdb.ReadHeadHeader(chainDb) == nil + if !emptyBlockChain && (cacheConfig.StateScheme == rawdb.PathScheme) { + // When using path scheme, and the stored state trie is not empty, + // WriteOrTestGenBlock is not able to recover EmptyRootHash state trie node. + // In that case Nitro doesn't test genblock, but just returns the BlockChain. + return GetBlockChain(chainDb, cacheConfig, chainConfig, txLookupLimit) + } + + err := WriteOrTestGenblock(chainDb, cacheConfig, initData, chainConfig, initMessage, accountsPerSync) if err != nil { return nil, err } diff --git a/execution/gethexec/blockchain_test.go b/execution/gethexec/blockchain_test.go new file mode 100644 index 0000000000..375488cedc --- /dev/null +++ b/execution/gethexec/blockchain_test.go @@ -0,0 +1,18 @@ +// Copyright 2021-2024, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package gethexec + +import ( + "testing" + "time" +) + +func TestGetStateHistory(t *testing.T) { + maxBlockSpeed := time.Millisecond * 250 + expectedStateHistory := uint64(345600) + actualStateHistory := getStateHistory(maxBlockSpeed) + if actualStateHistory != expectedStateHistory { + t.Errorf("Expected state history to be %d, but got %d", expectedStateHistory, actualStateHistory) + } +} diff --git a/execution/gethexec/forwarder.go b/execution/gethexec/forwarder.go index 984c7224e8..cdb4f394e5 100644 --- a/execution/gethexec/forwarder.go +++ b/execution/gethexec/forwarder.go @@ -35,15 +35,6 @@ type ForwarderConfig struct { RetryInterval time.Duration `koanf:"retry-interval"` } -var DefaultTestForwarderConfig = ForwarderConfig{ - ConnectionTimeout: 2 * time.Second, - IdleConnectionTimeout: 2 * time.Second, - MaxIdleConnections: 1, - RedisUrl: "", - UpdateInterval: time.Millisecond * 10, - RetryInterval: time.Millisecond * 3, -} - var DefaultNodeForwarderConfig = ForwarderConfig{ ConnectionTimeout: 30 * time.Second, IdleConnectionTimeout: 15 * time.Second, diff --git a/execution/gethexec/node.go b/execution/gethexec/node.go index 8ee16095d9..93f643b8a1 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -57,6 +57,9 @@ type Config struct { } func (c *Config) Validate() error { + if err := c.Caching.Validate(); err != nil { + return err + } if err := c.Sequencer.Validate(); err != nil { return err } @@ -105,31 +108,6 @@ var ConfigDefault = Config{ EnablePrefetchBlock: true, } -func ConfigDefaultNonSequencerTest() *Config { - config := ConfigDefault - config.Caching = TestCachingConfig - config.ParentChainReader = headerreader.TestConfig - config.Sequencer.Enable = false - config.Forwarder = DefaultTestForwarderConfig - config.ForwardingTarget = "null" - - _ = config.Validate() - - return &config -} - -func ConfigDefaultTest() *Config { - config := ConfigDefault - config.Caching = TestCachingConfig - config.Sequencer = TestSequencerConfig - config.ParentChainReader = headerreader.TestConfig - config.ForwardingTarget = "null" - - _ = config.Validate() - - return &config -} - type ConfigFetcher func() *Config type ExecutionNode struct { diff --git a/execution/gethexec/sequencer.go b/execution/gethexec/sequencer.go index c5e97342d2..e620e6ccd1 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -132,24 +132,6 @@ var DefaultSequencerConfig = SequencerConfig{ EnableProfiling: false, } -var TestSequencerConfig = SequencerConfig{ - Enable: true, - MaxBlockSpeed: time.Millisecond * 10, - MaxRevertGasReject: params.TxGas + 10000, - MaxAcceptableTimestampDelta: time.Hour, - SenderWhitelist: "", - Forwarder: DefaultTestForwarderConfig, - QueueSize: 128, - QueueTimeout: time.Second * 5, - NonceCacheSize: 4, - MaxTxDataSize: 95000, - NonceFailureCacheSize: 1024, - NonceFailureCacheExpiry: time.Second, - ExpectedSurplusSoftThreshold: "default", - ExpectedSurplusHardThreshold: "default", - EnableProfiling: false, -} - func SequencerConfigAddOptions(prefix string, f *flag.FlagSet) { f.Bool(prefix+".enable", DefaultSequencerConfig.Enable, "act and post to l1 as sequencer") f.Duration(prefix+".max-block-speed", DefaultSequencerConfig.MaxBlockSpeed, "minimum delay between blocks (sets a maximum speed of block production)") diff --git a/system_tests/block_validator_test.go b/system_tests/block_validator_test.go index b4dafbff15..6b4e6d2088 100644 --- a/system_tests/block_validator_test.go +++ b/system_tests/block_validator_test.go @@ -16,6 +16,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -68,6 +69,8 @@ func testBlockValidatorSimple(t *testing.T, opts Options) { builder := NewNodeBuilder(ctx).DefaultConfig(t, true) builder = builder.WithWasmRootDir(opts.wasmRootDir) + // For now PathDB is not supported when using block validation + builder.execConfig.Caching.StateScheme = rawdb.HashScheme builder.nodeConfig = l1NodeConfigA builder.chainConfig = chainConfig builder.L2Info = nil diff --git a/system_tests/common_test.go b/system_tests/common_test.go index cb424e75ef..7c6fb2aca0 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -20,6 +20,7 @@ import ( "time" "github.com/go-redis/redis/v8" + "github.com/offchainlabs/nitro/arbos" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbos/util" "github.com/offchainlabs/nitro/arbstate/daprovider" @@ -67,7 +68,6 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/offchainlabs/nitro/arbnode" - "github.com/offchainlabs/nitro/arbos" "github.com/offchainlabs/nitro/arbutil" _ "github.com/offchainlabs/nitro/execution/nodeInterface" "github.com/offchainlabs/nitro/solgen/go/bridgegen" @@ -76,6 +76,7 @@ import ( "github.com/offchainlabs/nitro/solgen/go/upgrade_executorgen" "github.com/offchainlabs/nitro/statetransfer" "github.com/offchainlabs/nitro/util/testhelpers" + "github.com/offchainlabs/nitro/util/testhelpers/env" "github.com/offchainlabs/nitro/util/testhelpers/github" ) @@ -151,6 +152,74 @@ func (tc *TestClient) EnsureTxSucceededWithTimeout(transaction *types.Transactio return EnsureTxSucceededWithTimeout(tc.ctx, tc.Client, transaction, timeout) } +var TestCachingConfig = gethexec.CachingConfig{ + Archive: false, + BlockCount: 128, + BlockAge: 30 * time.Minute, + TrieTimeLimit: time.Hour, + TrieDirtyCache: 1024, + TrieCleanCache: 600, + SnapshotCache: 400, + DatabaseCache: 2048, + SnapshotRestoreGasLimit: 300_000_000_000, + MaxNumberOfBlocksToSkipStateSaving: 0, + MaxAmountOfGasToSkipStateSaving: 0, + StylusLRUCache: 0, + StateScheme: env.GetTestStateScheme(), +} + +var DefaultTestForwarderConfig = gethexec.ForwarderConfig{ + ConnectionTimeout: 2 * time.Second, + IdleConnectionTimeout: 2 * time.Second, + MaxIdleConnections: 1, + RedisUrl: "", + UpdateInterval: time.Millisecond * 10, + RetryInterval: time.Millisecond * 3, +} + +var TestSequencerConfig = gethexec.SequencerConfig{ + Enable: true, + MaxBlockSpeed: time.Millisecond * 10, + MaxRevertGasReject: params.TxGas + 10000, + MaxAcceptableTimestampDelta: time.Hour, + SenderWhitelist: "", + Forwarder: DefaultTestForwarderConfig, + QueueSize: 128, + QueueTimeout: time.Second * 5, + NonceCacheSize: 4, + MaxTxDataSize: 95000, + NonceFailureCacheSize: 1024, + NonceFailureCacheExpiry: time.Second, + ExpectedSurplusSoftThreshold: "default", + ExpectedSurplusHardThreshold: "default", + EnableProfiling: false, +} + +func ExecConfigDefaultNonSequencerTest() *gethexec.Config { + config := gethexec.ConfigDefault + config.Caching = TestCachingConfig + config.ParentChainReader = headerreader.TestConfig + config.Sequencer.Enable = false + config.Forwarder = DefaultTestForwarderConfig + config.ForwardingTarget = "null" + + _ = config.Validate() + + return &config +} + +func ExecConfigDefaultTest() *gethexec.Config { + config := gethexec.ConfigDefault + config.Caching = TestCachingConfig + config.Sequencer = TestSequencerConfig + config.ParentChainReader = headerreader.TestConfig + config.ForwardingTarget = "null" + + _ = config.Validate() + + return &config +} + type NodeBuilder struct { // NodeBuilder configuration ctx context.Context @@ -195,11 +264,11 @@ func (b *NodeBuilder) DefaultConfig(t *testing.T, withL1 bool) *NodeBuilder { b.L1Info = NewL1TestInfo(t) b.L2Info = NewArbTestInfo(t, b.chainConfig.ChainID) b.dataDir = t.TempDir() - b.l1StackConfig = createStackConfigForTest(b.dataDir) - b.l2StackConfig = createStackConfigForTest(b.dataDir) + b.l1StackConfig = testhelpers.CreateStackConfigForTest(b.dataDir) + b.l2StackConfig = testhelpers.CreateStackConfigForTest(b.dataDir) cp := valnode.TestValidationConfig b.valnodeConfig = &cp - b.execConfig = gethexec.ConfigDefaultTest() + b.execConfig = ExecConfigDefaultTest() return b } @@ -237,7 +306,7 @@ func (b *NodeBuilder) CheckConfig(t *testing.T) { b.nodeConfig = arbnode.ConfigDefaultL1Test() } if b.execConfig == nil { - b.execConfig = gethexec.ConfigDefaultTest() + b.execConfig = ExecConfigDefaultTest() } if b.L1Info == nil { b.L1Info = NewL1TestInfo(t) @@ -687,23 +756,6 @@ func (c *staticNodeConfigFetcher) Started() bool { return true } -func createStackConfigForTest(dataDir string) *node.Config { - stackConf := node.DefaultConfig - stackConf.DataDir = dataDir - stackConf.UseLightweightKDF = true - stackConf.WSPort = 0 - stackConf.WSModules = append(stackConf.WSModules, "eth", "debug") - stackConf.HTTPPort = 0 - stackConf.HTTPHost = "" - stackConf.HTTPModules = append(stackConf.HTTPModules, "eth", "debug") - stackConf.P2P.NoDiscovery = true - stackConf.P2P.NoDial = true - stackConf.P2P.ListenAddr = "" - stackConf.P2P.NAT = nil - stackConf.DBEngine = "leveldb" // TODO Try pebble again in future once iterator race condition issues are fixed - return &stackConf -} - func createRedisGroup(ctx context.Context, t *testing.T, streamName string, client redis.UniversalClient) { t.Helper() // Stream name and group name are the same. @@ -815,7 +867,7 @@ func createTestL1BlockChain(t *testing.T, l1info info) (info, *ethclient.Client, if l1info == nil { l1info = NewL1TestInfo(t) } - stackConfig := createStackConfigForTest(t.TempDir()) + stackConfig := testhelpers.CreateStackConfigForTest(t.TempDir()) l1info.GenerateAccount("Faucet") chainConfig := params.ArbitrumDevTestChainConfig() @@ -949,7 +1001,7 @@ func createL2BlockChainWithStackConfig( var stack *node.Node var err error if stackConfig == nil { - stackConfig = createStackConfigForTest(dataDir) + stackConfig = testhelpers.CreateStackConfigForTest(dataDir) } stack, err = node.New(stackConfig) Require(t, err) @@ -977,7 +1029,7 @@ func createL2BlockChainWithStackConfig( if cacheConfig != nil { coreCacheConfig = gethexec.DefaultCacheConfigFor(stack, cacheConfig) } - blockchain, err := gethexec.WriteOrTestBlockChain(chainDb, coreCacheConfig, initReader, chainConfig, initMessage, gethexec.ConfigDefaultTest().TxLookupLimit, 0) + blockchain, err := gethexec.WriteOrTestBlockChain(chainDb, coreCacheConfig, initReader, chainConfig, initMessage, ExecConfigDefaultTest().TxLookupLimit, 0) Require(t, err) return l2info, stack, chainDb, arbDb, blockchain @@ -1030,14 +1082,14 @@ func Create2ndNodeWithConfig( nodeConfig = arbnode.ConfigDefaultL1NonSequencerTest() } if execConfig == nil { - execConfig = gethexec.ConfigDefaultNonSequencerTest() + execConfig = ExecConfigDefaultNonSequencerTest() } feedErrChan := make(chan error, 10) l1rpcClient := l1stack.Attach() l1client := ethclient.NewClient(l1rpcClient) if stackConfig == nil { - stackConfig = createStackConfigForTest(t.TempDir()) + stackConfig = testhelpers.CreateStackConfigForTest(t.TempDir()) } l2stack, err := node.New(stackConfig) Require(t, err) @@ -1060,7 +1112,7 @@ func Create2ndNodeWithConfig( chainConfig := firstExec.ArbInterface.BlockChain().Config() coreCacheConfig := gethexec.DefaultCacheConfigFor(l2stack, &execConfig.Caching) - l2blockchain, err := gethexec.WriteOrTestBlockChain(l2chainDb, coreCacheConfig, initReader, chainConfig, initMessage, gethexec.ConfigDefaultTest().TxLookupLimit, 0) + l2blockchain, err := gethexec.WriteOrTestBlockChain(l2chainDb, coreCacheConfig, initReader, chainConfig, initMessage, ExecConfigDefaultTest().TxLookupLimit, 0) Require(t, err) AddDefaultValNode(t, ctx, nodeConfig, true, "", valnodeConfig.Wasm.RootPath) diff --git a/system_tests/das_test.go b/system_tests/das_test.go index 6d67ce4adb..41a0ce62b1 100644 --- a/system_tests/das_test.go +++ b/system_tests/das_test.go @@ -30,6 +30,7 @@ import ( "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/util/headerreader" + "github.com/offchainlabs/nitro/util/testhelpers" "golang.org/x/exp/slog" ) @@ -154,7 +155,7 @@ func TestDASRekey(t *testing.T) { // Restart the node on the new keyset against the new DAS server running on the same disk as the first with new keys builder.nodeConfig.DataAvailability.RPCAggregator = aggConfigForBackend(t, backendConfigB) - builder.l2StackConfig = createStackConfigForTest(builder.dataDir) + builder.l2StackConfig = testhelpers.CreateStackConfigForTest(builder.dataDir) cleanup := builder.BuildL2OnL1(t) defer cleanup() diff --git a/system_tests/debug_trace_test.go b/system_tests/debug_trace_test.go index 1a83e5ad2f..13d9ed834b 100644 --- a/system_tests/debug_trace_test.go +++ b/system_tests/debug_trace_test.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" ) @@ -22,6 +23,8 @@ func TestDebugTraceCallForRecentBlock(t *testing.T) { defer cancel() builder := NewNodeBuilder(ctx).DefaultConfig(t, true) builder.execConfig.Caching.Archive = true + // For now Archive node should use HashScheme + builder.execConfig.Caching.StateScheme = rawdb.HashScheme cleanup := builder.Build(t) defer cleanup() builder.L2Info.GenerateAccount("User2") diff --git a/system_tests/forwarder_test.go b/system_tests/forwarder_test.go index d29e82c12c..2919377d6f 100644 --- a/system_tests/forwarder_test.go +++ b/system_tests/forwarder_test.go @@ -17,7 +17,6 @@ import ( "github.com/alicebob/miniredis/v2" "github.com/ethereum/go-ethereum/ethclient" "github.com/offchainlabs/nitro/arbnode" - "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/util/redisutil" ) @@ -39,7 +38,7 @@ func TestStaticForwarder(t *testing.T) { clientA := builder.L2.Client nodeConfigB := arbnode.ConfigDefaultL1Test() - execConfigB := gethexec.ConfigDefaultTest() + execConfigB := ExecConfigDefaultTest() execConfigB.Sequencer.Enable = false nodeConfigB.Sequencer = false nodeConfigB.DelayedSequencer.Enable = false @@ -110,7 +109,7 @@ func createForwardingNode(t *testing.T, builder *NodeBuilder, ipcPath string, re nodeConfig.Sequencer = false nodeConfig.DelayedSequencer.Enable = false nodeConfig.BatchPoster.Enable = false - execConfig := gethexec.ConfigDefaultTest() + execConfig := ExecConfigDefaultTest() execConfig.Sequencer.Enable = false execConfig.Forwarder.RedisUrl = redisUrl execConfig.ForwardingTarget = fallbackPath @@ -264,7 +263,7 @@ func TestRedisForwarder(t *testing.T) { tx := builder.L2Info.PrepareTx(userA, userB, builder.L2Info.TransferGas, transferAmount, nil) sendFunc := func() error { return forwardingClient.SendTransaction(ctx, tx) } - if err := tryWithTimeout(ctx, sendFunc, gethexec.DefaultTestForwarderConfig.UpdateInterval*10); err != nil { + if err := tryWithTimeout(ctx, sendFunc, DefaultTestForwarderConfig.UpdateInterval*10); err != nil { t.Fatalf("Client: %v, error sending transaction: %v", i, err) } _, err := EnsureTxSucceeded(ctx, seqClients[i], tx) @@ -309,7 +308,7 @@ func TestRedisForwarderFallbackNoRedis(t *testing.T) { builder.L2Info.GenerateAccount(user) tx := builder.L2Info.PrepareTx("Owner", "User2", builder.L2Info.TransferGas, transferAmount, nil) sendFunc := func() error { return forwardingClient.SendTransaction(ctx, tx) } - err := tryWithTimeout(ctx, sendFunc, gethexec.DefaultTestForwarderConfig.UpdateInterval*10) + err := tryWithTimeout(ctx, sendFunc, DefaultTestForwarderConfig.UpdateInterval*10) Require(t, err) _, err = builder.L2.EnsureTxSucceeded(tx) diff --git a/system_tests/full_challenge_impl_test.go b/system_tests/full_challenge_impl_test.go index bf95c390ba..ddc229074c 100644 --- a/system_tests/full_challenge_impl_test.go +++ b/system_tests/full_challenge_impl_test.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" @@ -262,6 +263,8 @@ func RunChallengeTest(t *testing.T, asserterIsCorrect bool, useStubs bool, chall if useStubs { mockSpawn, valStack = createMockValidationNode(t, ctx, &builder.valnodeConfig.Arbitrator) } else { + // For now validation only works with HashScheme set + builder.execConfig.Caching.StateScheme = rawdb.HashScheme _, valStack = createTestValidationNode(t, ctx, builder.valnodeConfig) } configByValidationNode(conf, valStack) diff --git a/system_tests/program_test.go b/system_tests/program_test.go index b748739cdc..20bc873adc 100644 --- a/system_tests/program_test.go +++ b/system_tests/program_test.go @@ -20,6 +20,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -1474,6 +1475,9 @@ func setupProgramTest(t *testing.T, jit bool, builderOpts ...func(*NodeBuilder)) opt(builder) } + // setupProgramTest is being called by tests that validate blocks. + // For now validation only works with HashScheme set. + builder.execConfig.Caching.StateScheme = rawdb.HashScheme builder.nodeConfig.BlockValidator.Enable = false builder.nodeConfig.Staker.Enable = true builder.nodeConfig.BatchPoster.Enable = true @@ -1679,7 +1683,7 @@ func testWasmRecreate(t *testing.T, builder *NodeBuilder, storeTx *types.Transac Require(t, err) testDir := t.TempDir() - nodeBStack := createStackConfigForTest(testDir) + nodeBStack := testhelpers.CreateStackConfigForTest(testDir) nodeB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{stackConfig: nodeBStack}) _, err = EnsureTxSucceeded(ctx, nodeB.Client, storeTx) @@ -1816,7 +1820,7 @@ func TestWasmStoreRebuilding(t *testing.T) { Require(t, err) testDir := t.TempDir() - nodeBStack := createStackConfigForTest(testDir) + nodeBStack := testhelpers.CreateStackConfigForTest(testDir) nodeB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{stackConfig: nodeBStack}) _, err = EnsureTxSucceeded(ctx, nodeB.Client, storeTx) diff --git a/system_tests/pruning_test.go b/system_tests/pruning_test.go index 041781ac48..90ac3c6909 100644 --- a/system_tests/pruning_test.go +++ b/system_tests/pruning_test.go @@ -35,6 +35,8 @@ func TestPruning(t *testing.T) { defer cancel() builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + // PathScheme prunes the state trie by itself, so only HashScheme should be tested + builder.execConfig.Caching.StateScheme = rawdb.HashScheme _ = builder.Build(t) l2cleanupDone := false defer func() { diff --git a/system_tests/recreatestate_rpc_test.go b/system_tests/recreatestate_rpc_test.go index de123aee78..985ca09f19 100644 --- a/system_tests/recreatestate_rpc_test.go +++ b/system_tests/recreatestate_rpc_test.go @@ -95,11 +95,13 @@ func removeStatesFromDb(t *testing.T, bc *core.BlockChain, db ethdb.Database, fr func TestRecreateStateForRPCNoDepthLimit(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - execConfig := gethexec.ConfigDefaultTest() + execConfig := ExecConfigDefaultTest() execConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth execConfig.Sequencer.MaxBlockSpeed = 0 execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 execConfig.Caching.Archive = true + // For now Archive node should use HashScheme + execConfig.Caching.StateScheme = rawdb.HashScheme execConfig.Caching.SnapshotCache = 0 // disable snapshots // disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there execConfig.Caching.TrieCleanCache = 0 @@ -131,11 +133,13 @@ func TestRecreateStateForRPCBigEnoughDepthLimit(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() depthGasLimit := int64(256 * util.NormalizeL2GasForL1GasInitial(800_000, params.GWei)) - execConfig := gethexec.ConfigDefaultTest() + execConfig := ExecConfigDefaultTest() execConfig.RPC.MaxRecreateStateDepth = depthGasLimit execConfig.Sequencer.MaxBlockSpeed = 0 execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 execConfig.Caching.Archive = true + // For now Archive node should use HashScheme + execConfig.Caching.StateScheme = rawdb.HashScheme // disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there execConfig.Caching.TrieCleanCache = 0 execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0 @@ -166,11 +170,13 @@ func TestRecreateStateForRPCBigEnoughDepthLimit(t *testing.T) { func TestRecreateStateForRPCDepthLimitExceeded(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - execConfig := gethexec.ConfigDefaultTest() + execConfig := ExecConfigDefaultTest() execConfig.RPC.MaxRecreateStateDepth = int64(200) execConfig.Sequencer.MaxBlockSpeed = 0 execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 execConfig.Caching.Archive = true + // For now Archive node should use HashScheme + execConfig.Caching.StateScheme = rawdb.HashScheme // disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there execConfig.Caching.TrieCleanCache = 0 execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0 @@ -201,11 +207,13 @@ func TestRecreateStateForRPCMissingBlockParent(t *testing.T) { var headerCacheLimit uint64 = 512 ctx, cancel := context.WithCancel(context.Background()) defer cancel() - execConfig := gethexec.ConfigDefaultTest() + execConfig := ExecConfigDefaultTest() execConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth execConfig.Sequencer.MaxBlockSpeed = 0 execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 execConfig.Caching.Archive = true + // For now Archive node should use HashScheme + execConfig.Caching.StateScheme = rawdb.HashScheme // disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there execConfig.Caching.TrieCleanCache = 0 execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0 @@ -247,11 +255,13 @@ func TestRecreateStateForRPCBeyondGenesis(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - execConfig := gethexec.ConfigDefaultTest() + execConfig := ExecConfigDefaultTest() execConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth execConfig.Sequencer.MaxBlockSpeed = 0 execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 execConfig.Caching.Archive = true + // For now Archive node should use HashScheme + execConfig.Caching.StateScheme = rawdb.HashScheme // disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there execConfig.Caching.TrieCleanCache = 0 execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 0 @@ -283,11 +293,13 @@ func TestRecreateStateForRPCBlockNotFoundWhileRecreating(t *testing.T) { var blockCacheLimit uint64 = 256 ctx, cancel := context.WithCancel(context.Background()) defer cancel() - execConfig := gethexec.ConfigDefaultTest() + execConfig := ExecConfigDefaultTest() execConfig.RPC.MaxRecreateStateDepth = arbitrum.InfiniteMaxRecreateStateDepth execConfig.Sequencer.MaxBlockSpeed = 0 execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 execConfig.Caching.Archive = true + // For now Archive node should use HashScheme + execConfig.Caching.StateScheme = rawdb.HashScheme // disable trie/Database.cleans cache, so as states removed from ChainDb won't be cached there execConfig.Caching.TrieCleanCache = 0 @@ -329,7 +341,7 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, cacheConfig ctx, cancel := context.WithCancel(context.Background()) defer cancel() - execConfig := gethexec.ConfigDefaultTest() + execConfig := ExecConfigDefaultTest() execConfig.RPC.MaxRecreateStateDepth = maxRecreateStateDepth execConfig.Sequencer.MaxBlockSpeed = 0 execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 @@ -427,8 +439,10 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, cacheConfig } func TestSkippingSavingStateAndRecreatingAfterRestart(t *testing.T) { - cacheConfig := gethexec.TestCachingConfig + cacheConfig := TestCachingConfig cacheConfig.Archive = true + // For now Archive node should use HashScheme + cacheConfig.StateScheme = rawdb.HashScheme cacheConfig.SnapshotCache = 0 // disable snapshots cacheConfig.BlockAge = 0 // use only Caching.BlockCount to keep only last N blocks in dirties cache, no matter how new they are @@ -468,7 +482,7 @@ func TestSkippingSavingStateAndRecreatingAfterRestart(t *testing.T) { func TestGettingStateForRPCFullNode(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - execConfig := gethexec.ConfigDefaultTest() + execConfig := ExecConfigDefaultTest() execConfig.Caching.SnapshotCache = 0 // disable snapshots execConfig.Caching.BlockAge = 0 // use only Caching.BlockCount to keep only last N blocks in dirties cache, no matter how new they are execConfig.Sequencer.MaxBlockSpeed = 0 @@ -510,8 +524,10 @@ func TestGettingStateForRPCFullNode(t *testing.T) { func TestGettingStateForRPCHybridArchiveNode(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - execConfig := gethexec.ConfigDefaultTest() + execConfig := ExecConfigDefaultTest() execConfig.Caching.Archive = true + // For now Archive node should use HashScheme + execConfig.Caching.StateScheme = rawdb.HashScheme execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 128 execConfig.Caching.BlockCount = 128 execConfig.Caching.SnapshotCache = 0 // disable snapshots @@ -558,6 +574,8 @@ func TestStateAndHeaderForRecentBlock(t *testing.T) { defer cancel() builder := NewNodeBuilder(ctx).DefaultConfig(t, true) builder.execConfig.Caching.Archive = true + // For now Archive node should use HashScheme + builder.execConfig.Caching.StateScheme = rawdb.HashScheme builder.execConfig.RPC.MaxRecreateStateDepth = 0 cleanup := builder.Build(t) defer cleanup() diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index 268d59ac98..8f9507aea2 100644 --- a/system_tests/retryable_test.go +++ b/system_tests/retryable_test.go @@ -22,7 +22,6 @@ import ( "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/arbos/retryables" "github.com/offchainlabs/nitro/arbos/util" - "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/solgen/go/mocksgen" @@ -940,7 +939,7 @@ func elevateL2Basefee(t *testing.T, ctx context.Context, builder *NodeBuilder) { _, err = precompilesgen.NewArbosTest(common.HexToAddress("0x69"), builder.L2.Client) Require(t, err, "failed to deploy ArbosTest") - burnAmount := gethexec.ConfigDefaultTest().RPC.RPCGasCap + burnAmount := ExecConfigDefaultTest().RPC.RPCGasCap burnTarget := uint64(5 * l2pricing.InitialSpeedLimitPerSecondV6 * l2pricing.InitialBacklogTolerance) for i := uint64(0); i < (burnTarget+burnAmount)/burnAmount; i++ { burnArbGas := arbostestabi.Methods["burnArbGas"] diff --git a/system_tests/seqfeed_test.go b/system_tests/seqfeed_test.go index e3a98b4961..9637c7d4fc 100644 --- a/system_tests/seqfeed_test.go +++ b/system_tests/seqfeed_test.go @@ -333,7 +333,7 @@ func testBlockHashComparison(t *testing.T, blockHash *common.Hash, mustMismatch } wsBroadcastServer.Broadcast(&broadcastMessage) - // By now, even though block hash mismatch, the transaction should still be processed + // For now, even though block hash mismatch, the transaction should still be processed _, err = WaitForTx(ctx, testClient.Client, tx.Hash(), time.Second*15) if err != nil { t.Fatal("error waiting for tx:", err) diff --git a/system_tests/snap_sync_test.go b/system_tests/snap_sync_test.go index 31d5ea8492..a04d9f5bf3 100644 --- a/system_tests/snap_sync_test.go +++ b/system_tests/snap_sync_test.go @@ -10,6 +10,7 @@ import ( "testing" "time" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/params" @@ -17,6 +18,7 @@ import ( "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos/l2pricing" "github.com/offchainlabs/nitro/util" + "github.com/offchainlabs/nitro/util/testhelpers" ) func TestSnapSync(t *testing.T) { @@ -27,6 +29,7 @@ func TestSnapSync(t *testing.T) { // 1st node with sequencer, stays up all the time. builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.execConfig.Caching.StateScheme = rawdb.HashScheme builder.L2Info = NewBlockChainTestInfo( t, types.NewArbitrumSigner(types.NewLondonSigner(builder.chainConfig.ChainID)), big.NewInt(l2pricing.InitialBaseFeeWei*2), @@ -38,7 +41,7 @@ func TestSnapSync(t *testing.T) { // 2nd node without sequencer, syncs up to the first node. // This node will be stopped in middle and arbitrumdata will be deleted. testDir := t.TempDir() - nodeBStack := createStackConfigForTest(testDir) + nodeBStack := testhelpers.CreateStackConfigForTest(testDir) nodeBConfig := builder.nodeConfig nodeBConfig.BatchPoster.Enable = false nodeBParams := &SecondNodeParams{ diff --git a/system_tests/staker_test.go b/system_tests/staker_test.go index 52f16614f7..f57b68ad8a 100644 --- a/system_tests/staker_test.go +++ b/system_tests/staker_test.go @@ -76,6 +76,9 @@ func stakerTestImpl(t *testing.T, faultyStaker bool, honestStakerInactive bool) transferGas, ) + // For now validation only works with HashScheme set + builder.execConfig.Caching.StateScheme = rawdb.HashScheme + builder.nodeConfig.BatchPoster.MaxDelay = -1000 * time.Hour cleanupA := builder.Build(t) defer cleanupA() diff --git a/system_tests/state_fuzz_test.go b/system_tests/state_fuzz_test.go index bb78bda480..713aefcfba 100644 --- a/system_tests/state_fuzz_test.go +++ b/system_tests/state_fuzz_test.go @@ -28,6 +28,7 @@ import ( "github.com/offchainlabs/nitro/arbstate" "github.com/offchainlabs/nitro/arbstate/daprovider" "github.com/offchainlabs/nitro/statetransfer" + "github.com/offchainlabs/nitro/util/testhelpers/env" ) func BuildBlock( @@ -137,8 +138,10 @@ func FuzzStateTransition(f *testing.F) { ChainConfig: chainConfig, SerializedChainConfig: serializedChainConfig, } + cacheConfig := core.DefaultCacheConfigWithScheme(env.GetTestStateScheme()) stateRoot, err := arbosState.InitializeArbosInDatabase( chainDb, + cacheConfig, statetransfer.NewMemoryInitDataReader(&statetransfer.ArbosInitializationInfo{}), chainConfig, initMessage, @@ -148,7 +151,8 @@ func FuzzStateTransition(f *testing.F) { if err != nil { panic(err) } - statedb, err := state.New(stateRoot, state.NewDatabase(chainDb), nil) + trieDBConfig := cacheConfig.TriedbConfig() + statedb, err := state.New(stateRoot, state.NewDatabaseWithConfig(chainDb, trieDBConfig), nil) if err != nil { panic(err) } diff --git a/system_tests/staterecovery_test.go b/system_tests/staterecovery_test.go index 1dd4be2444..42faee7e0d 100644 --- a/system_tests/staterecovery_test.go +++ b/system_tests/staterecovery_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/trie" @@ -19,6 +20,8 @@ func TestRectreateMissingStates(t *testing.T) { defer cancel() builder := NewNodeBuilder(ctx).DefaultConfig(t, true) builder.execConfig.Caching.Archive = true + // For now Archive node should use HashScheme + builder.execConfig.Caching.StateScheme = rawdb.HashScheme builder.execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 16 builder.execConfig.Caching.SnapshotCache = 0 // disable snapshots _ = builder.Build(t) @@ -53,7 +56,10 @@ func TestRectreateMissingStates(t *testing.T) { chainDb, err := stack.OpenDatabaseWithExtraOptions("l2chaindata", 0, 0, "l2chaindata/", false, conf.PersistentConfigDefault.Pebble.ExtraOptions("l2chaindata")) Require(t, err) defer chainDb.Close() - cacheConfig := gethexec.DefaultCacheConfigFor(stack, &gethexec.TestCachingConfig) + cachingConfig := TestCachingConfig + // For now Archive node should use HashScheme + cachingConfig.StateScheme = rawdb.HashScheme + cacheConfig := gethexec.DefaultCacheConfigFor(stack, &cachingConfig) bc, err := gethexec.GetBlockChain(chainDb, cacheConfig, builder.chainConfig, builder.execConfig.TxLookupLimit) Require(t, err) err = staterecovery.RecreateMissingStates(chainDb, bc, cacheConfig, 1) diff --git a/system_tests/triedb_race_test.go b/system_tests/triedb_race_test.go index 9f14f08898..609a4c0b60 100644 --- a/system_tests/triedb_race_test.go +++ b/system_tests/triedb_race_test.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/arbitrum" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" "github.com/offchainlabs/nitro/util/testhelpers" @@ -23,6 +24,8 @@ func TestTrieDBCommitRace(t *testing.T) { builder.execConfig.Sequencer.MaxBlockSpeed = 0 builder.execConfig.Sequencer.MaxTxDataSize = 150 // 1 test tx ~= 110 builder.execConfig.Caching.Archive = true + // For now Archive node should use HashScheme + builder.execConfig.Caching.StateScheme = rawdb.HashScheme builder.execConfig.Caching.BlockCount = 127 builder.execConfig.Caching.BlockAge = 0 builder.execConfig.Caching.MaxNumberOfBlocksToSkipStateSaving = 127 diff --git a/util/testhelpers/env/env.go b/util/testhelpers/env/env.go new file mode 100644 index 0000000000..27d74465de --- /dev/null +++ b/util/testhelpers/env/env.go @@ -0,0 +1,23 @@ +// Copyright 2024, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package env + +import ( + "os" + + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/log" +) + +// There are two CI steps, one to run tests using the path state scheme, and one to run tests using the hash state scheme. +// An environment variable controls that behavior. +func GetTestStateScheme() string { + envTestStateScheme := os.Getenv("TEST_STATE_SCHEME") + stateScheme := rawdb.PathScheme + if envTestStateScheme == rawdb.PathScheme || envTestStateScheme == rawdb.HashScheme { + stateScheme = envTestStateScheme + } + log.Debug("test state scheme", "testStateScheme", stateScheme) + return stateScheme +} diff --git a/util/testhelpers/stackconfig.go b/util/testhelpers/stackconfig.go new file mode 100644 index 0000000000..a3c794ff28 --- /dev/null +++ b/util/testhelpers/stackconfig.go @@ -0,0 +1,23 @@ +// Copyright 2021-2024, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package testhelpers + +import "github.com/ethereum/go-ethereum/node" + +func CreateStackConfigForTest(dataDir string) *node.Config { + stackConf := node.DefaultConfig + stackConf.DataDir = dataDir + stackConf.UseLightweightKDF = true + stackConf.WSPort = 0 + stackConf.WSModules = append(stackConf.WSModules, "eth", "debug") + stackConf.HTTPPort = 0 + stackConf.HTTPHost = "" + stackConf.HTTPModules = append(stackConf.HTTPModules, "eth", "debug") + stackConf.P2P.NoDiscovery = true + stackConf.P2P.NoDial = true + stackConf.P2P.ListenAddr = "" + stackConf.P2P.NAT = nil + stackConf.DBEngine = "pebble" + return &stackConf +}