diff --git a/.dockerignore b/.dockerignore index e142afd073..51424900e8 100644 --- a/.dockerignore +++ b/.dockerignore @@ -9,6 +9,7 @@ go-ethereum/tests **/*.yml contracts/build contracts/cache/ +safe-smart-account/build/ solgen/go **/node_modules diff --git a/.github/workflows/arbitrator-ci.yml b/.github/workflows/arbitrator-ci.yml index 3ec3327392..adbf562e31 100644 --- a/.github/workflows/arbitrator-ci.yml +++ b/.github/workflows/arbitrator-ci.yml @@ -71,14 +71,14 @@ jobs: - name: Install rust stable uses: dtolnay/rust-toolchain@stable with: - toolchain: "1.76" + toolchain: 'stable' components: 'llvm-tools-preview, rustfmt, clippy' - name: Install rust nightly uses: dtolnay/rust-toolchain@nightly id: install-rust-nightly with: - toolchain: "nightly-2024-02-04" + toolchain: 'nightly' targets: 'wasm32-wasi, wasm32-unknown-unknown' components: 'rust-src, rustfmt, clippy' @@ -156,7 +156,7 @@ jobs: run: echo "$HOME/wabt-prefix/bin" >> "$GITHUB_PATH" - name: Make arbitrator libraries - run: make -j wasm-ci-build STYLUS_NIGHTLY_VER="+nightly-2024-02-04" + run: make -j wasm-ci-build - name: Clippy check run: cargo clippy --all --manifest-path arbitrator/Cargo.toml -- -D warnings diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc5cd68a90..b9fcfba7fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -141,17 +141,57 @@ 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 ./...` - stdbuf -oL gotestsum --format short-verbose --packages="$packages" --rerun-fails=1 --no-color=false -- ./... -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,./go-ethereum/... -timeout 20m -parallel=8 > >(stdbuf -oL tee full.log | grep -vE "INFO|seal") - - - name: run tests with race detection + 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 -- -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 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 ./...` - stdbuf -oL gotestsum --format short-verbose --packages="$packages" --rerun-fails=1 --no-color=false -- ./... -race -timeout 30m -parallel=8 > >(stdbuf -oL tee full.log | grep -vE "INFO|seal") + 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 > >(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 - name: run redis tests if: matrix.test-mode == 'defaults' @@ -161,19 +201,34 @@ jobs: if: matrix.test-mode == 'challenge' run: | packages=`go list ./...` - stdbuf -oL gotestsum --format short-verbose --packages="$packages" --rerun-fails=1 --no-color=false -- ./... -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,./go-ethereum/... -parallel=8 -tags=challengetest -run=TestChallenge > >(stdbuf -oL tee full.log | grep -vE "INFO|seal") + 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 -- -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 - name: run stylus tests if: matrix.test-mode == 'stylus' run: | packages=`go list ./...` - stdbuf -oL gotestsum --format short-verbose --packages="$packages" --rerun-fails=1 --no-color=false -- ./... -timeout 60m -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,./go-ethereum/... -parallel=8 -tags=stylustest -run="TestProgramArbitrator" > >(stdbuf -oL tee full.log | grep -vE "INFO|seal") + 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 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 - name: run long stylus tests if: matrix.test-mode == 'long' run: | packages=`go list ./...` - stdbuf -oL gotestsum --format short-verbose --packages="$packages" --rerun-fails=1 --no-color=false -- ./... -timeout 60m -coverprofile=coverage.txt -covermode=atomic -coverpkg=./...,./go-ethereum/... -parallel=8 -tags=stylustest -run="TestProgramLong" > >(stdbuf -oL tee full.log | grep -vE "INFO|seal") + 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 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 - name: Archive detailed run log uses: actions/upload-artifact@v3 @@ -189,4 +244,3 @@ jobs: files: ./coverage.txt,./coverage-redis.txt verbose: false token: ${{ secrets.CODECOV_TOKEN }} - diff --git a/.gitmodules b/.gitmodules index d7b61d862b..d4d26282ae 100644 --- a/.gitmodules +++ b/.gitmodules @@ -32,3 +32,6 @@ [submodule "arbitrator/langs/bf"] path = arbitrator/langs/bf url = https://github.com/OffchainLabs/stylus-sdk-bf.git +[submodule "safe-smart-account"] + path = safe-smart-account + url = https://github.com/safe-global/safe-smart-account.git diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000000..3c032078a4 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +18 diff --git a/Dockerfile b/Dockerfile index 2fced8fade..ea473055aa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,6 +32,8 @@ WORKDIR /workspace COPY contracts/package.json contracts/yarn.lock contracts/ RUN cd contracts && yarn install COPY contracts contracts/ +COPY safe-smart-account safe-smart-account/ +RUN cd safe-smart-account && yarn install COPY Makefile . RUN . ~/.bashrc && NITRO_BUILD_IGNORE_TIMESTAMPS=1 make build-solidity @@ -43,8 +45,8 @@ FROM wasm-base AS wasm-libs-builder # clang / lld used by soft-float wasm RUN apt-get update && \ apt-get install -y clang=1:14.0-55.7~deb12u1 lld=1:14.0-55.7~deb12u1 wabt - # pinned rust 1.75.0 -RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain 1.75.0 --target x86_64-unknown-linux-gnu wasm32-unknown-unknown wasm32-wasi + # pinned rust 1.80.0 +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain 1.80.0 --target x86_64-unknown-linux-gnu wasm32-unknown-unknown wasm32-wasi COPY ./Makefile ./ COPY arbitrator/Cargo.* arbitrator/ COPY arbitrator/arbutil arbitrator/arbutil @@ -82,6 +84,7 @@ COPY ./wavmio ./wavmio COPY ./zeroheavy ./zeroheavy COPY ./contracts/src/precompiles/ ./contracts/src/precompiles/ COPY ./contracts/package.json ./contracts/yarn.lock ./contracts/ +COPY ./safe-smart-account ./safe-smart-account COPY ./solgen/gen.go ./solgen/ COPY ./fastcache ./fastcache COPY ./go-ethereum ./go-ethereum @@ -91,7 +94,7 @@ COPY --from=contracts-builder workspace/contracts/node_modules/@offchainlabs/upg COPY --from=contracts-builder workspace/.make/ .make/ RUN PATH="$PATH:/usr/local/go/bin" NITRO_BUILD_IGNORE_TIMESTAMPS=1 make build-wasm-bin -FROM rust:1.75-slim-bookworm AS prover-header-builder +FROM rust:1.80-slim-bookworm AS prover-header-builder WORKDIR /workspace RUN export DEBIAN_FRONTEND=noninteractive && \ apt-get update && \ @@ -100,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 @@ -116,7 +120,7 @@ RUN NITRO_BUILD_IGNORE_TIMESTAMPS=1 make build-prover-header FROM scratch AS prover-header-export COPY --from=prover-header-builder /workspace/target/ / -FROM rust:1.75-slim-bookworm AS prover-builder +FROM rust:1.80-slim-bookworm AS prover-builder WORKDIR /workspace RUN export DEBIAN_FRONTEND=noninteractive && \ apt-get update && \ @@ -128,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 @@ -138,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 @@ -179,6 +190,7 @@ COPY ./Makefile ./ COPY ./arbitrator ./arbitrator COPY ./solgen ./solgen COPY ./contracts ./contracts +COPY ./safe-smart-account ./safe-smart-account RUN NITRO_BUILD_IGNORE_TIMESTAMPS=1 make build-replay-env FROM debian:bookworm-slim AS machine-versions @@ -226,6 +238,7 @@ COPY . ./ COPY --from=contracts-builder workspace/contracts/build/ contracts/build/ COPY --from=contracts-builder workspace/contracts/out/ contracts/out/ COPY --from=contracts-builder workspace/contracts/node_modules/@offchainlabs/upgrade-executor/build/contracts/src/UpgradeExecutor.sol/UpgradeExecutor.json contracts/node_modules/@offchainlabs/upgrade-executor/build/contracts/src/UpgradeExecutor.sol/ +COPY --from=contracts-builder workspace/safe-smart-account/build/ safe-smart-account/build/ COPY --from=contracts-builder workspace/.make/ .make/ COPY --from=prover-header-export / target/ COPY --from=brotli-library-export / target/ diff --git a/Makefile b/Makefile index dc9b4e3ddf..c05249466a 100644 --- a/Makefile +++ b/Makefile @@ -81,7 +81,8 @@ prover_dir = arbitrator/prover/ rust_prover_files = $(wildcard $(prover_dir)/src/*.* $(prover_dir)/src/*/*.* $(prover_dir)/*.toml $(prover_dir)/*.rs) $(rust_arbutil_files) $(prover_direct_includes) $(arb_brotli_files) wasm_lib = arbitrator/wasm-libraries -wasm_lib_deps = $(wildcard $(wasm_lib)/$(1)/*.toml $(wasm_lib)/$(1)/src/*.rs $(wasm_lib)/$(1)/*.rs) $(rust_arbutil_files) $(arb_brotli_files) .make/machines +wasm_lib_cargo = $(wasm_lib)/.cargo/config.toml +wasm_lib_deps = $(wildcard $(wasm_lib)/$(1)/*.toml $(wasm_lib)/$(1)/src/*.rs $(wasm_lib)/$(1)/*.rs) $(wasm_lib_cargo) $(rust_arbutil_files) $(arb_brotli_files) .make/machines wasm_lib_go_abi = $(call wasm_lib_deps,go-abi) wasm_lib_forward = $(call wasm_lib_deps,forward) wasm_lib_user_host_trait = $(call wasm_lib_deps,user-host-trait) @@ -287,8 +288,8 @@ $(arbitrator_jit): $(DEP_PREDICATE) $(jit_files) cargo build --manifest-path arbitrator/Cargo.toml --release -p jit ${CARGOFLAGS} install arbitrator/target/release/jit $@ -$(arbitrator_cases)/rust/$(wasm32_wasi)/%.wasm: $(arbitrator_cases)/rust/src/bin/%.rs $(arbitrator_cases)/rust/src/lib.rs - cargo build --manifest-path $(arbitrator_cases)/rust/Cargo.toml --release --target wasm32-wasi --bin $(patsubst $(arbitrator_cases)/rust/$(wasm32_wasi)/%.wasm,%, $@) +$(arbitrator_cases)/rust/$(wasm32_wasi)/%.wasm: $(arbitrator_cases)/rust/src/bin/%.rs $(arbitrator_cases)/rust/src/lib.rs $(arbitrator_cases)/rust/.cargo/config.toml + cargo build --manifest-path $(arbitrator_cases)/rust/Cargo.toml --release --target wasm32-wasi --config $(arbitrator_cases)/rust/.cargo/config.toml --bin $(patsubst $(arbitrator_cases)/rust/$(wasm32_wasi)/%.wasm,%, $@) $(arbitrator_cases)/go/testcase.wasm: $(arbitrator_cases)/go/*.go .make/solgen cd $(arbitrator_cases)/go && GOOS=wasip1 GOARCH=wasm go build -o testcase.wasm @@ -300,7 +301,7 @@ $(arbitrator_generated_header): $(DEP_PREDICATE) $(stylus_files) @touch -c $@ # cargo might decide to not rebuild the header $(output_latest)/wasi_stub.wasm: $(DEP_PREDICATE) $(call wasm_lib_deps,wasi-stub) - cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-unknown-unknown --package wasi-stub + cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-unknown-unknown --config $(wasm_lib_cargo) --package wasi-stub install arbitrator/wasm-libraries/$(wasm32_unknown)/wasi_stub.wasm $@ arbitrator/wasm-libraries/soft-float/SoftFloat/build/Wasm-Clang/softfloat.a: $(DEP_PREDICATE) \ @@ -342,23 +343,23 @@ $(output_latest)/soft-float.wasm: $(DEP_PREDICATE) \ --export wavm__f64_promote_f32 $(output_latest)/host_io.wasm: $(DEP_PREDICATE) $(call wasm_lib_deps,host-io) $(wasm_lib_go_abi) - cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --package host-io + cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --config $(wasm_lib_cargo) --package host-io install arbitrator/wasm-libraries/$(wasm32_wasi)/host_io.wasm $@ $(output_latest)/user_host.wasm: $(DEP_PREDICATE) $(wasm_lib_user_host) $(rust_prover_files) $(output_latest)/forward_stub.wasm .make/machines - cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --package user-host + cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --config $(wasm_lib_cargo) --package user-host install arbitrator/wasm-libraries/$(wasm32_wasi)/user_host.wasm $@ $(output_latest)/program_exec.wasm: $(DEP_PREDICATE) $(call wasm_lib_deps,program-exec) $(rust_prover_files) .make/machines - cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --package program-exec + cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --config $(wasm_lib_cargo) --package program-exec install arbitrator/wasm-libraries/$(wasm32_wasi)/program_exec.wasm $@ $(output_latest)/user_test.wasm: $(DEP_PREDICATE) $(call wasm_lib_deps,user-test) $(rust_prover_files) .make/machines - cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --package user-test + cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --config $(wasm_lib_cargo) --package user-test install arbitrator/wasm-libraries/$(wasm32_wasi)/user_test.wasm $@ $(output_latest)/arbcompress.wasm: $(DEP_PREDICATE) $(call wasm_lib_deps,brotli) $(wasm_lib_go_abi) - cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --package arbcompress + cargo build --manifest-path arbitrator/wasm-libraries/Cargo.toml --release --target wasm32-wasi --config $(wasm_lib_cargo) --package arbcompress install arbitrator/wasm-libraries/$(wasm32_wasi)/arbcompress.wasm $@ $(output_latest)/forward.wasm: $(DEP_PREDICATE) $(wasm_lib_forward) .make/machines @@ -428,10 +429,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 +456,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 @@ -494,12 +495,14 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(prover_bin) go run solgen/gen.go @touch $@ -.make/solidity: $(DEP_PREDICATE) contracts/src/*/*.sol .make/yarndeps $(ORDER_ONLY_PREDICATE) .make +.make/solidity: $(DEP_PREDICATE) safe-smart-account/contracts/*/*.sol safe-smart-account/contracts/*.sol contracts/src/*/*.sol .make/yarndeps $(ORDER_ONLY_PREDICATE) .make + yarn --cwd safe-smart-account build yarn --cwd contracts build yarn --cwd contracts build:forge:yul @touch $@ .make/yarndeps: $(DEP_PREDICATE) contracts/package.json contracts/yarn.lock $(ORDER_ONLY_PREDICATE) .make + yarn --cwd safe-smart-account install yarn --cwd contracts install @touch $@ diff --git a/arbcompress/native.go b/arbcompress/native.go index 4624d6222e..8244010979 100644 --- a/arbcompress/native.go +++ b/arbcompress/native.go @@ -12,7 +12,10 @@ package arbcompress #include "arbitrator.h" */ import "C" -import "fmt" +import ( + "errors" + "fmt" +) type u8 = C.uint8_t type u32 = C.uint32_t @@ -44,6 +47,8 @@ func Compress(input []byte, level uint32, dictionary Dictionary) ([]byte, error) return output, nil } +var ErrOutputWontFit = errors.New("output won't fit in maxsize") + func Decompress(input []byte, maxSize int) ([]byte, error) { return DecompressWithDictionary(input, maxSize, EmptyDictionary) } @@ -54,6 +59,9 @@ func DecompressWithDictionary(input []byte, maxSize int, dictionary Dictionary) inbuf := sliceToBuffer(input) status := C.brotli_decompress(inbuf, outbuf, C.Dictionary(dictionary)) + if status == C.BrotliStatus_NeedsMoreOutput { + return nil, ErrOutputWontFit + } if status != C.BrotliStatus_Success { return nil, fmt.Errorf("failed decompression: %d", status) } diff --git a/arbitrator/Cargo.lock b/arbitrator/Cargo.lock index a89dc5e97e..79a9117a31 100644 --- a/arbitrator/Cargo.lock +++ b/arbitrator/Cargo.lock @@ -37,7 +37,7 @@ dependencies = [ "cfg-if 1.0.0", "once_cell", "version_check", - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -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.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "arbitrary" version = "1.3.2" @@ -114,19 +184,40 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.72" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", "cfg-if 1.0.0", "libc", "miniz_oxide", - "object 0.35.0", + "object 0.36.2", "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.13", + "eyre", + "gperftools", + "hex", + "prover", + "serde", + "serde_json", + "serde_with 3.9.0", +] + [[package]] name = "bincode" version = "1.3.3" @@ -144,9 +235,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitvec" @@ -156,6 +247,7 @@ checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", + "serde", "tap", "wyz", ] @@ -187,9 +279,9 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "blst" -version = "0.3.11" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" +checksum = "4378725facc195f1a538864863f6de233b500a8862747e7f165078a419d5e874" dependencies = [ "cc", "glob", @@ -252,9 +344,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "fca2be1d5c43812bae364ee3f30b3afcb7877cf59f4aeb94c66f313a41d2fac9" [[package]] name = "c-kzg" @@ -281,15 +373,20 @@ 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" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" +checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" dependencies = [ "jobserver", "libc", - "once_cell", ] [[package]] @@ -304,6 +401,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 +456,64 @@ dependencies = [ "vec_map", ] +[[package]] +name = "clap" +version = "4.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim 0.11.1", +] + +[[package]] +name = "clap_derive" +version = "4.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + [[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 +619,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.13", + "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" @@ -492,12 +717,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "darling_core 0.20.9", - "darling_macro 0.20.9", + "darling_core 0.20.10", + "darling_macro 0.20.10", ] [[package]] @@ -516,15 +741,16 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "syn 2.0.66", + "strsim 0.11.1", + "syn 2.0.72", ] [[package]] @@ -540,13 +766,13 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "darling_core 0.20.9", + "darling_core 0.20.10", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -562,6 +788,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" @@ -575,15 +811,15 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", - "syn 1.0.109", + "syn 2.0.72", ] [[package]] @@ -633,9 +869,9 @@ dependencies = [ [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "enum-iterator" @@ -643,7 +879,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,25 +902,36 @@ 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.72", +] + [[package]] name = "enumset" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d" +checksum = "d07a4b049558765cef5f0c1a273c3fc57084d768b44d2f98127aef4cceb17293" dependencies = [ "enumset_derive", ] [[package]] name = "enumset_derive" -version = "0.8.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" +checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242" dependencies = [ - "darling 0.20.9", + "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -684,6 +940,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 +1031,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 +1080,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 +1106,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,16 +1153,18 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", + "serde", ] [[package]] name = "indexmap" -version = "2.2.6" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" dependencies = [ "equivalent", "hashbrown 0.14.5", + "serde", ] [[package]] @@ -871,6 +1192,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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itertools" version = "0.10.5" @@ -912,9 +1250,9 @@ dependencies = [ [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] @@ -939,9 +1277,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "leb128" @@ -968,9 +1306,9 @@ dependencies = [ [[package]] name = "llvm-sys" -version = "150.1.3" +version = "150.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd60e740af945d99c2446a52e3ab8cdba2f740a40a16c51f6871bdea2abc687" +checksum = "88d6891afbe90a8be244f769dfe1db0b3c4880b8c44b12a6d0f7ab848d89b26d" dependencies = [ "cc", "lazy_static", @@ -991,15 +1329,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" dependencies = [ "hashbrown 0.14.5", ] @@ -1024,9 +1362,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" @@ -1069,9 +1407,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] @@ -1119,9 +1457,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", @@ -1136,6 +1474,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" @@ -1144,7 +1488,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1199,23 +1543,23 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1229,9 +1573,9 @@ dependencies = [ [[package]] name = "object" -version = "0.35.0" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" +checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" dependencies = [ "memchr", ] @@ -1242,6 +1586,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "oorandom" +version = "11.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" + [[package]] name = "opaque-debug" version = "0.3.1" @@ -1277,11 +1627,54 @@ 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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" + +[[package]] +name = "plotters-svg" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" +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" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "dee4364d9f3b902ef14fab8a1ddffb783a1cb6b4bba3bfc1fa3922732c7de97f" +dependencies = [ + "zerocopy 0.6.6", +] [[package]] name = "proc-macro-crate" @@ -1318,9 +1711,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.84" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -1331,10 +1724,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 +1745,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", @@ -1462,11 +1859,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -1483,9 +1880,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", @@ -1495,9 +1892,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -1506,9 +1903,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "region" @@ -1600,6 +1997,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" @@ -1626,9 +2032,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] @@ -1646,22 +2052,23 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -1673,7 +2080,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.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.3.0", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros 3.9.0", + "time", ] [[package]] @@ -1688,6 +2113,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "serde_with_macros" +version = "3.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" +dependencies = [ + "darling 0.20.10", + "proc-macro2", + "quote", + "syn 2.0.72", +] + [[package]] name = "sha2" version = "0.9.9" @@ -1795,13 +2232,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 +2255,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", @@ -1861,9 +2304,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -1878,9 +2321,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.14" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "textwrap" @@ -1893,22 +2336,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1920,6 +2363,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,11 +2403,21 @@ 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" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -1946,9 +2430,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" @@ -1956,7 +2440,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "toml_datetime", "winnow", ] @@ -1980,7 +2464,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -2012,9 +2496,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "user-host-trait" @@ -2027,11 +2511,17 @@ dependencies = [ "ruint2", ] +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" [[package]] name = "vec_map" @@ -2041,9 +2531,19 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] [[package]] name = "wasi" @@ -2072,7 +2572,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", "wasm-bindgen-shared", ] @@ -2094,7 +2594,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2148,7 +2648,7 @@ dependencies = [ "backtrace", "bytes", "cfg-if 1.0.0", - "enum-iterator", + "enum-iterator 0.7.0", "enumset", "lazy_static", "leb128", @@ -2237,7 +2737,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 +2757,7 @@ dependencies = [ "crossbeam-queue", "dashmap", "derivative", - "enum-iterator", + "enum-iterator 0.7.0", "fnv", "indexmap 1.9.3", "lazy_static", @@ -2278,8 +2778,8 @@ version = "0.121.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab" dependencies = [ - "bitflags 2.5.0", - "indexmap 2.2.6", + "bitflags 2.6.0", + "indexmap 2.3.0", "semver", ] @@ -2304,6 +2804,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 +2842,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" @@ -2362,25 +2890,25 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.52.5", + "windows_x86_64_msvc 0.52.6", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -2390,9 +2918,9 @@ checksum = "cd761fd3eb9ab8cc1ed81e56e567f02dd82c4c837e48ac3b2181b9ffc5060807" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -2402,15 +2930,15 @@ checksum = "cab0cf703a96bab2dc0c02c0fa748491294bf9b7feb27e1f4f96340f208ada0e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -2420,9 +2948,9 @@ checksum = "8cfdbe89cc9ad7ce618ba34abc34bbb6c36d99e96cae2245b7943cd75ee773d0" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -2432,15 +2960,15 @@ checksum = "b4dd9b0c0e9ece7bb22e84d70d01b71c6d6248b81a3c60d11869451b4cb24784" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -2450,9 +2978,9 @@ checksum = "ff1e4aa646495048ec7f3ffddc411e1d829c026a2ec62b39da15c1055e406eaa" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" @@ -2474,22 +3002,43 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "854e949ac82d619ee9a14c66a1b674ac730422372ccb759ce0c39cabcf2bf8e6" dependencies = [ - "zerocopy-derive", + "byteorder", + "zerocopy-derive 0.6.6", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy-derive" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -2509,5 +3058,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] 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/brotli/src/lib.rs b/arbitrator/brotli/src/lib.rs index 5bc2e8dcf6..b2c808b1a4 100644 --- a/arbitrator/brotli/src/lib.rs +++ b/arbitrator/brotli/src/lib.rs @@ -192,7 +192,7 @@ pub fn compress_fixed<'a>( BrotliEncoderDestroyInstance(state); // SAFETY: brotli initialized this span of bytes - let output = mem::transmute(&output[..out_len]); + let output = mem::transmute::<&[MaybeUninit], &[u8]>(&output[..out_len]); Ok(output) } } @@ -304,7 +304,7 @@ pub fn decompress_fixed<'a>( BrotliDecoderDestroyInstance(state); // SAFETY: brotli initialized this span of bytes - let output = mem::transmute(&output[..out_len]); + let output = mem::transmute::<&[MaybeUninit], &[u8]>(&output[..out_len]); Ok(output) } } diff --git a/arbitrator/jit/src/caller_env.rs b/arbitrator/jit/src/caller_env.rs index f4fbff10ae..41240d3d98 100644 --- a/arbitrator/jit/src/caller_env.rs +++ b/arbitrator/jit/src/caller_env.rs @@ -8,7 +8,6 @@ use rand::RngCore; use rand_pcg::Pcg32; use std::{ cmp::Ordering, - collections::{BTreeSet, BinaryHeap}, fmt::Debug, mem::{self, MaybeUninit}, }; @@ -102,7 +101,7 @@ impl MemAccess for JitMemAccess<'_> { self.view() .read_uninit(ptr.into(), &mut data) .expect("bad read"); - mem::transmute(data) + mem::transmute::>, Vec>(data) } } @@ -175,11 +174,3 @@ impl PartialOrd for TimeoutInfo { Some(self.cmp(other)) } } - -#[derive(Default, Debug)] -pub struct TimeoutState { - /// Contains tuples of (time, id) - pub times: BinaryHeap, - pub pending_ids: BTreeSet, - pub next_id: u32, -} diff --git a/arbitrator/jit/src/machine.rs b/arbitrator/jit/src/machine.rs index f51970c6dd..2a3c5c5616 100644 --- a/arbitrator/jit/src/machine.rs +++ b/arbitrator/jit/src/machine.rs @@ -15,7 +15,7 @@ use std::{ io::{BufReader, BufWriter, ErrorKind, Read}, net::TcpStream, sync::Arc, - time::{Duration, Instant}, + time::Instant, }; use thiserror::Error; use wasmer::{ @@ -322,8 +322,6 @@ pub struct ProcessEnv { pub socket: Option<(BufWriter, BufReader)>, /// A timestamp that helps with printing at various moments pub timestamp: Instant, - /// How long to wait on any child threads to compute a result - pub child_timeout: Duration, /// Whether the machine has reached the first wavmio instruction pub reached_wavmio: bool, } @@ -335,7 +333,6 @@ impl Default for ProcessEnv { debug: false, socket: None, timestamp: Instant::now(), - child_timeout: Duration::from_secs(15), reached_wavmio: false, } } diff --git a/arbitrator/langs/bf b/arbitrator/langs/bf index cb5750580f..92420f8f34 160000 --- a/arbitrator/langs/bf +++ b/arbitrator/langs/bf @@ -1 +1 @@ -Subproject commit cb5750580f6990b5166ffce83de11b766a25ca31 +Subproject commit 92420f8f34b53f3c1d47047f9f894820d506c565 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/fuzz/Cargo.lock b/arbitrator/prover/fuzz/Cargo.lock index 4966a07d3f..f0cc083864 100644 --- a/arbitrator/prover/fuzz/Cargo.lock +++ b/arbitrator/prover/fuzz/Cargo.lock @@ -17,6 +17,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c38b6b6b79f671c25e1a3e785b7b82d7562ffc9cd3efdc98627e5668a2472490" +[[package]] +name = "arbutil" +version = "0.1.0" +dependencies = [ + "digest 0.10.7", + "num_enum", + "sha2", + "sha3 0.10.8", +] + [[package]] name = "arrayvec" version = "0.7.2" @@ -36,14 +46,14 @@ dependencies = [ [[package]] name = "auto_impl" -version = "0.5.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7862e21c893d65a1650125d157eaeec691439379a1cee17ee49031b79236ada4" +checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -126,9 +136,9 @@ dependencies = [ [[package]] name = "byte-slice-cast" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87c5fdd0166095e1d463fc6cc01aa8ce547ad77a4e84d42eb6762b084e28067e" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "byteorder" @@ -169,6 +179,15 @@ dependencies = [ "vec_map", ] +[[package]] +name = "cpufeatures" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +dependencies = [ + "libc", +] + [[package]] name = "crossbeam-channel" version = "0.5.4" @@ -251,7 +270,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn", + "syn 1.0.109", ] [[package]] @@ -262,7 +281,7 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -273,7 +292,7 @@ checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -287,9 +306,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.3" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.2", "crypto-common", @@ -307,14 +326,20 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68b91989ae21441195d7d9b9993a2f9295c7e1a8c96255d8b729accddc124797" +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "ethbloom" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11da94e443c60508eb62cf256243a64da87304c2802ac2528847f79d750007ef" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" dependencies = [ "crunchy", - "fixed-hash", + "fixed-hash 0.8.0", "impl-codec", "impl-rlp", "scale-info", @@ -323,9 +348,9 @@ dependencies = [ [[package]] name = "ethereum" -version = "0.12.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23750149fe8834c0e24bb9adcbacbe06c45b9861f15df53e09f26cb7c4ab91ef" +checksum = "2e04d24d20b8ff2235cffbf242d5092de3aa45f77c5270ddbfadd2778ca13fea" dependencies = [ "bytes", "ethereum-types", @@ -333,33 +358,32 @@ dependencies = [ "hash256-std-hasher", "parity-scale-codec", "rlp", - "rlp-derive", "scale-info", "serde", - "sha3 0.10.1", - "triehash", + "sha3 0.10.8", + "trie-root", ] [[package]] name = "ethereum-types" -version = "0.13.1" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2827b94c556145446fcce834ca86b7abf0c39a805883fe20e72c5bfdb5a0dc6" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" dependencies = [ "ethbloom", - "fixed-hash", + "fixed-hash 0.8.0", "impl-codec", "impl-rlp", - "primitive-types", + "primitive-types 0.12.2", "scale-info", "uint", ] [[package]] name = "evm" -version = "0.36.0" +version = "0.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d388bbd18050623b996cc4ba0643971e2978693ad56ca8b7603080cfa5eaf738" +checksum = "767f43e9630cc36cf8ff2777cbb0121b055f0d1fd6eaaa13b46a1808f0d0e7e9" dependencies = [ "auto_impl", "environmental", @@ -369,48 +393,48 @@ dependencies = [ "evm-runtime", "log", "parity-scale-codec", - "primitive-types", + "primitive-types 0.12.2", "rlp", "scale-info", "serde", - "sha3 0.10.1", + "sha3 0.10.8", ] [[package]] name = "evm-core" -version = "0.36.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5fb3a449a544a67c879d2f74e1c3d9022de3ec31c9a20817015816f687aa2af" +checksum = "d1da6cedc5cedb4208e59467106db0d1f50db01b920920589f8e672c02fdc04f" dependencies = [ "parity-scale-codec", - "primitive-types", + "primitive-types 0.12.2", "scale-info", "serde", ] [[package]] name = "evm-gasometer" -version = "0.36.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "170a27b6e49b8279016afffcdc6ebae9225d5acff3a546ad8589929b091e7ac5" +checksum = "1dc0eb591abc5cd7b05bef6a036c2bb6c66ab6c5e0c5ce94bfe377ab670b1fd7" dependencies = [ "environmental", "evm-core", "evm-runtime", - "primitive-types", + "primitive-types 0.12.2", ] [[package]] name = "evm-runtime" -version = "0.36.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d48c2545a02e3a4d1a5184a96af11037334dce947b6bdb389b3503b3a6f8dcd" +checksum = "84bbe09b64ae13a29514048c1bb6fda6374ac0b4f6a1f15a443348ab88ef42cd" dependencies = [ "auto_impl", "environmental", "evm-core", - "primitive-types", - "sha3 0.10.1", + "primitive-types 0.12.2", + "sha3 0.10.8", ] [[package]] @@ -435,6 +459,18 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + [[package]] name = "fnv" version = "1.0.7" @@ -470,9 +506,9 @@ dependencies = [ [[package]] name = "hash-db" -version = "0.15.2" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" +checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" [[package]] name = "hash256-std-hasher" @@ -489,6 +525,12 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "heck" version = "0.3.3" @@ -545,7 +587,7 @@ checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -561,7 +603,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.11.2", +] + +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", ] [[package]] @@ -572,9 +624,12 @@ checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" [[package]] name = "keccak" -version = "0.1.0" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] [[package]] name = "lazy_static" @@ -582,11 +637,17 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + [[package]] name = "libc" -version = "0.2.125" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libfuzzer-sys" @@ -736,6 +797,27 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" +dependencies = [ + "proc-macro-crate 1.1.3", + "proc-macro2", + "quote", + "syn 2.0.46", +] + [[package]] name = "once_cell" version = "1.10.0" @@ -750,9 +832,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "parity-scale-codec" -version = "3.1.2" +version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8b44461635bbb1a0300f100a841e571e7d919c81c73075ef5d152ffdb521066" +checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" dependencies = [ "arrayvec", "bitvec", @@ -764,14 +846,14 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.1.2" +version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c45ed1f39709f5a89338fab50e59816b2e8815f5bb58276e7ddf9afd495f73f8" +checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 2.0.1", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -792,7 +874,18 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" dependencies = [ - "fixed-hash", + "fixed-hash 0.7.0", + "impl-codec", + "uint", +] + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash 0.8.0", "impl-codec", "impl-rlp", "scale-info", @@ -809,6 +902,16 @@ dependencies = [ "toml", ] +[[package]] +name = "proc-macro-crate" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +dependencies = [ + "toml_datetime", + "toml_edit", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -818,7 +921,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "version_check", ] @@ -835,23 +938,25 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.37" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" +checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "prover" version = "0.1.0" dependencies = [ + "arbutil", "bincode", "brotli2", "digest 0.9.0", "eyre", "fnv", "hex", + "lazy_static", "libc", "nom", "nom-leb128", @@ -866,6 +971,7 @@ dependencies = [ "static_assertions", "structopt", "wasmparser", + "wat", ] [[package]] @@ -877,7 +983,7 @@ dependencies = [ "hex", "lazy_static", "libfuzzer-sys", - "primitive-types", + "primitive-types 0.11.1", "prover", "rayon", "serde", @@ -887,9 +993,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.18" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -956,11 +1062,12 @@ dependencies = [ [[package]] name = "rlp" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "999508abb0ae792aabed2460c45b89106d97fe4adac593bdaef433c2605847b5" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ "bytes", + "rlp-derive", "rustc-hex", ] @@ -972,7 +1079,7 @@ checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1001,9 +1108,9 @@ checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "scale-info" -version = "2.1.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8980cafbe98a7ee7a9cc16b32ebce542c77883f512d83fbf2ddc8f6a85ea74c9" +checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" dependencies = [ "bitvec", "cfg-if", @@ -1014,14 +1121,14 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.1.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4260c630e8a8a33429d1688eff2f163f24c65a4e1b1578ef6b565061336e4b6f" +checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.1.3", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1032,22 +1139,22 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.137" +version = "1.0.194" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +checksum = "0b114498256798c94a0689e1a15fec6005dee8ac1f41de56404b67afc2a4b773" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.194" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.46", ] [[package]] @@ -1081,7 +1188,18 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn", + "syn 1.0.109", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", ] [[package]] @@ -1098,11 +1216,11 @@ dependencies = [ [[package]] name = "sha3" -version = "0.10.1" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881bf8156c87b6301fc5ca6b27f11eeb2761224c7081e69b409d5a1951a70c86" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest 0.10.3", + "digest 0.10.7", "keccak", ] @@ -1154,18 +1272,29 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] name = "syn" -version = "1.0.92" +version = "2.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" +checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] @@ -1200,7 +1329,7 @@ checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -1232,13 +1361,29 @@ dependencies = [ ] [[package]] -name = "triehash" -version = "0.8.4" +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.1.0", + "toml_datetime", + "winnow", +] + +[[package]] +name = "trie-root" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1631b201eb031b563d2e85ca18ec8092508e262a3196ce9bd10a67ec87b9f5c" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" dependencies = [ "hash-db", - "rlp", ] [[package]] @@ -1249,9 +1394,9 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "uint" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f03af7ccf01dd611cc450a0d10dbc9b745770d096473e2faf0ca6e2d66d1e0" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" dependencies = [ "byteorder", "crunchy", @@ -1259,6 +1404,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + [[package]] name = "unicode-segmentation" version = "1.9.0" @@ -1271,12 +1422,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" -[[package]] -name = "unicode-xid" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" - [[package]] name = "vec_map" version = "0.8.2" @@ -1295,13 +1440,43 @@ version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +[[package]] +name = "wasm-encoder" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad2b51884de9c7f4fe2fd1043fccb8dcad4b1e29558146ee57a144d15779f3f" +dependencies = [ + "leb128", +] + [[package]] name = "wasmparser" version = "0.84.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77dc97c22bb5ce49a47b745bed8812d30206eff5ef3af31424f2c1820c0974b2" dependencies = [ - "indexmap", + "indexmap 1.8.1", +] + +[[package]] +name = "wast" +version = "69.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ee37317321afde358e4d7593745942c48d6d17e0e6e943704de9bbee121e7a" +dependencies = [ + "leb128", + "memchr", + "unicode-width", + "wasm-encoder", +] + +[[package]] +name = "wat" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeb338ee8dee4d4cd05e6426683f21c5087dc7cfc8903e839ccf48d43332da3c" +dependencies = [ + "wast", ] [[package]] @@ -1326,6 +1501,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "winnow" +version = "0.5.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8434aeec7b290e8da5c3f0d628cb0eac6cabcb31d14bb74f779a08109a5914d6" +dependencies = [ + "memchr", +] + [[package]] name = "wyz" version = "0.5.0" diff --git a/arbitrator/prover/fuzz/Cargo.toml b/arbitrator/prover/fuzz/Cargo.toml index 08fcc863aa..7845b2a38e 100644 --- a/arbitrator/prover/fuzz/Cargo.toml +++ b/arbitrator/prover/fuzz/Cargo.toml @@ -15,7 +15,7 @@ eyre = "0.6.8" tokio = { version = "1.18.5", features = ["rt", "rt-multi-thread"] } serde = { version = "1.0.137", features = ["derive"] } hex = "0.4.3" -evm = "0.36.0" +evm = "0.41.1" serde_json = "1.0.81" primitive-types = "0.11.1" rayon = "1.5.1" 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..358876bd25 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(), @@ -1709,7 +1725,11 @@ impl Machine { /// finds the first module with the given name pub fn find_module(&self, name: &str) -> Result { - let Some(module) = self.modules.iter().position(|m| m.name() == name) else { + let Some(module) = self + .modules + .iter() + .position(|m| m.name().trim_end_matches(".wasm") == name) + else { let names: Vec<_> = self.modules.iter().map(|m| m.name()).collect(); let names = names.join(", "); bail!("module {} not found among: {names}", name.red()) @@ -1906,20 +1926,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 +1949,6 @@ impl Machine { continue; } self.status = MachineStatus::Errored; - module = &mut self.modules[self.pc.module()]; break; }}; } @@ -1949,7 +1959,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 +2018,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 +2037,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 +2047,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 +2058,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 +2080,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 +2511,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 +2523,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 +2562,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 +2685,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..4a1278b4cb 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,285 @@ 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) >> 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] + fn resize_and_set_odd() { + let merkle = Merkle::new_advanced(MerkleType::Value, vec![Bytes32::from([1; 32])], 20); + merkle.resize(9).expect("resize failed"); + merkle.set(8, Bytes32::from([2; 32])); + } + + #[test] + fn resize_and_set_even() { + let merkle = Merkle::new_advanced(MerkleType::Value, vec![Bytes32::from([1; 32])], 20); + merkle.resize(10).expect("resize failed"); + merkle.set(9, Bytes32::from([2; 32])); + } + + #[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!(", "); + } } - 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); + 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 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/prover/src/utils.rs b/arbitrator/prover/src/utils.rs index 49b4ea0c3d..48889e1199 100644 --- a/arbitrator/prover/src/utils.rs +++ b/arbitrator/prover/src/utils.rs @@ -82,13 +82,13 @@ struct RemoteRefType(pub [u8; 3]); impl From for RemoteRefType { fn from(value: RefType) -> Self { - unsafe { std::mem::transmute(value) } + unsafe { std::mem::transmute::(value) } } } impl From for RefType { fn from(value: RemoteRefType) -> Self { - unsafe { std::mem::transmute(value) } + unsafe { std::mem::transmute::(value) } } } diff --git a/arbitrator/prover/src/value.rs b/arbitrator/prover/src/value.rs index 4ec02f5463..6afffdf7a0 100644 --- a/arbitrator/prover/src/value.rs +++ b/arbitrator/prover/src/value.rs @@ -133,11 +133,7 @@ pub struct ProgramCounter { pub inst: u32, } -#[cfg(not(any( - target_pointer_width = "32", - target_pointer_width = "64", - target_pointer_width = "128" -)))] +#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64",)))] compile_error!("Architectures with less than a 32 bit pointer width are not supported"); impl ProgramCounter { diff --git a/arbitrator/prover/test-cases/rust/.cargo/config.toml b/arbitrator/prover/test-cases/rust/.cargo/config.toml new file mode 100644 index 0000000000..23ffbe67c1 --- /dev/null +++ b/arbitrator/prover/test-cases/rust/.cargo/config.toml @@ -0,0 +1,10 @@ +[build] +target = "wasm32-wasi" + +[target.wasm32-wasi] +rustflags = [ + "-C", "target-cpu=mvp", +] + +[unstable] +build-std = ["core", "panic_abort", "alloc", "std"] diff --git a/arbitrator/stylus/src/host.rs b/arbitrator/stylus/src/host.rs index 7854386e23..1afc1b4e51 100644 --- a/arbitrator/stylus/src/host.rs +++ b/arbitrator/stylus/src/host.rs @@ -64,7 +64,7 @@ where unsafe { data.set_len(len); self.view().read_uninit(ptr.into(), &mut data)?; - Ok(mem::transmute(data)) + Ok(mem::transmute::>, Vec>(data)) } } diff --git a/arbitrator/stylus/src/native.rs b/arbitrator/stylus/src/native.rs index 2858d59fdc..a7b996edf0 100644 --- a/arbitrator/stylus/src/native.rs +++ b/arbitrator/stylus/src/native.rs @@ -367,7 +367,7 @@ pub fn module(wasm: &[u8], compile: CompileConfig) -> Result> { Function::new_typed(&mut store, $($types)+ -> f64 { panic!("incomplete import") }) }; ($($types:tt)+) => { - Function::new_typed(&mut store, $($types)+ panic!("incomplete import")) + Function::new_typed(&mut store, $($types)+ -> () { panic!("incomplete import") }) }; } let mut imports = imports! { 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/stylus/tests/.cargo/config.toml b/arbitrator/stylus/tests/.cargo/config.toml index ff01b66852..702a5c04b3 100644 --- a/arbitrator/stylus/tests/.cargo/config.toml +++ b/arbitrator/stylus/tests/.cargo/config.toml @@ -3,6 +3,7 @@ target = "wasm32-unknown-unknown" [target.wasm32-unknown-unknown] rustflags = [ + "-C", "target-cpu=mvp", "-C", "link-arg=-zstack-size=8192", # "-C", "link-arg=--export=__heap_base", # "-C", "link-arg=--export=__data_end", diff --git a/arbitrator/stylus/tests/create/.cargo/config b/arbitrator/stylus/tests/create/.cargo/config deleted file mode 100644 index f4e8c002fc..0000000000 --- a/arbitrator/stylus/tests/create/.cargo/config +++ /dev/null @@ -1,2 +0,0 @@ -[build] -target = "wasm32-unknown-unknown" diff --git a/arbitrator/stylus/tests/create/.cargo/config.toml b/arbitrator/stylus/tests/create/.cargo/config.toml new file mode 100644 index 0000000000..ea2ec38b12 --- /dev/null +++ b/arbitrator/stylus/tests/create/.cargo/config.toml @@ -0,0 +1,7 @@ +[build] +target = "wasm32-unknown-unknown" + +[target.wasm32-unknown-unknown] +rustflags = [ + "-C", "target-cpu=mvp", +] diff --git a/arbitrator/stylus/tests/evm-data/.cargo/config b/arbitrator/stylus/tests/evm-data/.cargo/config deleted file mode 100644 index f4e8c002fc..0000000000 --- a/arbitrator/stylus/tests/evm-data/.cargo/config +++ /dev/null @@ -1,2 +0,0 @@ -[build] -target = "wasm32-unknown-unknown" diff --git a/arbitrator/stylus/tests/evm-data/.cargo/config.toml b/arbitrator/stylus/tests/evm-data/.cargo/config.toml new file mode 100644 index 0000000000..ea2ec38b12 --- /dev/null +++ b/arbitrator/stylus/tests/evm-data/.cargo/config.toml @@ -0,0 +1,7 @@ +[build] +target = "wasm32-unknown-unknown" + +[target.wasm32-unknown-unknown] +rustflags = [ + "-C", "target-cpu=mvp", +] diff --git a/arbitrator/stylus/tests/fallible/.cargo/config b/arbitrator/stylus/tests/fallible/.cargo/config deleted file mode 100644 index f4e8c002fc..0000000000 --- a/arbitrator/stylus/tests/fallible/.cargo/config +++ /dev/null @@ -1,2 +0,0 @@ -[build] -target = "wasm32-unknown-unknown" diff --git a/arbitrator/stylus/tests/fallible/.cargo/config.toml b/arbitrator/stylus/tests/fallible/.cargo/config.toml new file mode 100644 index 0000000000..ea2ec38b12 --- /dev/null +++ b/arbitrator/stylus/tests/fallible/.cargo/config.toml @@ -0,0 +1,7 @@ +[build] +target = "wasm32-unknown-unknown" + +[target.wasm32-unknown-unknown] +rustflags = [ + "-C", "target-cpu=mvp", +] diff --git a/arbitrator/stylus/tests/log/.cargo/config b/arbitrator/stylus/tests/log/.cargo/config deleted file mode 100644 index f4e8c002fc..0000000000 --- a/arbitrator/stylus/tests/log/.cargo/config +++ /dev/null @@ -1,2 +0,0 @@ -[build] -target = "wasm32-unknown-unknown" diff --git a/arbitrator/stylus/tests/log/.cargo/config.toml b/arbitrator/stylus/tests/log/.cargo/config.toml new file mode 100644 index 0000000000..ea2ec38b12 --- /dev/null +++ b/arbitrator/stylus/tests/log/.cargo/config.toml @@ -0,0 +1,7 @@ +[build] +target = "wasm32-unknown-unknown" + +[target.wasm32-unknown-unknown] +rustflags = [ + "-C", "target-cpu=mvp", +] diff --git a/arbitrator/stylus/tests/multicall/.cargo/config b/arbitrator/stylus/tests/multicall/.cargo/config deleted file mode 100644 index f4e8c002fc..0000000000 --- a/arbitrator/stylus/tests/multicall/.cargo/config +++ /dev/null @@ -1,2 +0,0 @@ -[build] -target = "wasm32-unknown-unknown" diff --git a/arbitrator/stylus/tests/multicall/.cargo/config.toml b/arbitrator/stylus/tests/multicall/.cargo/config.toml new file mode 100644 index 0000000000..ea2ec38b12 --- /dev/null +++ b/arbitrator/stylus/tests/multicall/.cargo/config.toml @@ -0,0 +1,7 @@ +[build] +target = "wasm32-unknown-unknown" + +[target.wasm32-unknown-unknown] +rustflags = [ + "-C", "target-cpu=mvp", +] diff --git a/arbitrator/stylus/tests/read-return-data/.cargo/config b/arbitrator/stylus/tests/read-return-data/.cargo/config deleted file mode 100644 index aa59d2ee1c..0000000000 --- a/arbitrator/stylus/tests/read-return-data/.cargo/config +++ /dev/null @@ -1,3 +0,0 @@ -[build] -target = "wasm32-unknown-unknown" - diff --git a/arbitrator/stylus/tests/read-return-data/.cargo/config.toml b/arbitrator/stylus/tests/read-return-data/.cargo/config.toml new file mode 100644 index 0000000000..ea2ec38b12 --- /dev/null +++ b/arbitrator/stylus/tests/read-return-data/.cargo/config.toml @@ -0,0 +1,7 @@ +[build] +target = "wasm32-unknown-unknown" + +[target.wasm32-unknown-unknown] +rustflags = [ + "-C", "target-cpu=mvp", +] diff --git a/arbitrator/stylus/tests/sdk-storage/.cargo/config b/arbitrator/stylus/tests/sdk-storage/.cargo/config deleted file mode 100644 index f4e8c002fc..0000000000 --- a/arbitrator/stylus/tests/sdk-storage/.cargo/config +++ /dev/null @@ -1,2 +0,0 @@ -[build] -target = "wasm32-unknown-unknown" diff --git a/arbitrator/stylus/tests/sdk-storage/.cargo/config.toml b/arbitrator/stylus/tests/sdk-storage/.cargo/config.toml new file mode 100644 index 0000000000..ea2ec38b12 --- /dev/null +++ b/arbitrator/stylus/tests/sdk-storage/.cargo/config.toml @@ -0,0 +1,7 @@ +[build] +target = "wasm32-unknown-unknown" + +[target.wasm32-unknown-unknown] +rustflags = [ + "-C", "target-cpu=mvp", +] diff --git a/arbitrator/stylus/tests/storage/.cargo/config b/arbitrator/stylus/tests/storage/.cargo/config deleted file mode 100644 index f4e8c002fc..0000000000 --- a/arbitrator/stylus/tests/storage/.cargo/config +++ /dev/null @@ -1,2 +0,0 @@ -[build] -target = "wasm32-unknown-unknown" diff --git a/arbitrator/stylus/tests/storage/.cargo/config.toml b/arbitrator/stylus/tests/storage/.cargo/config.toml new file mode 100644 index 0000000000..ea2ec38b12 --- /dev/null +++ b/arbitrator/stylus/tests/storage/.cargo/config.toml @@ -0,0 +1,7 @@ +[build] +target = "wasm32-unknown-unknown" + +[target.wasm32-unknown-unknown] +rustflags = [ + "-C", "target-cpu=mvp", +] diff --git a/arbitrator/wasm-libraries/.cargo/config.toml b/arbitrator/wasm-libraries/.cargo/config.toml new file mode 100644 index 0000000000..797b856fbf --- /dev/null +++ b/arbitrator/wasm-libraries/.cargo/config.toml @@ -0,0 +1,12 @@ +[target.wasm32-unknown-unknown] +rustflags = [ + "-C", "target-cpu=mvp", +] + +[target.wasm32-wasi] +rustflags = [ + "-C", "target-cpu=mvp", +] + +[unstable] +build-std = ["core", "panic_abort", "alloc", "std"] diff --git a/arbitrator/wasm-libraries/Cargo.lock b/arbitrator/wasm-libraries/Cargo.lock index bea50f6592..7620ff538b 100644 --- a/arbitrator/wasm-libraries/Cargo.lock +++ b/arbitrator/wasm-libraries/Cargo.lock @@ -27,9 +27,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "ansi_term" @@ -87,9 +87,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "bincode" @@ -108,9 +108,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitvec" @@ -120,6 +120,7 @@ checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ "funty", "radium", + "serde", "tap", "wyz", ] @@ -160,9 +161,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytecheck" @@ -188,9 +189,9 @@ dependencies = [ [[package]] name = "bytes" -version = "1.5.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "fca2be1d5c43812bae364ee3f30b3afcb7877cf59f4aeb94c66f313a41d2fac9" [[package]] name = "caller-env" @@ -272,12 +273,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "darling_core 0.20.8", - "darling_macro 0.20.8", + "darling_core 0.20.10", + "darling_macro 0.20.10", ] [[package]] @@ -296,15 +297,15 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -320,13 +321,13 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "darling_core 0.20.8", + "darling_core 0.20.10", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -342,15 +343,15 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", - "syn 1.0.109", + "syn 2.0.72", ] [[package]] @@ -374,9 +375,9 @@ dependencies = [ [[package]] name = "either" -version = "1.10.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "enum-iterator" @@ -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.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c280b9e6b3ae19e152d8e31cf47f18389781e119d4013a2a2bb0180e5facc635" +dependencies = [ + "enum-iterator-derive 1.4.0", ] [[package]] @@ -398,25 +408,36 @@ 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.72", +] + [[package]] name = "enumset" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d" +checksum = "d07a4b049558765cef5f0c1a273c3fc57084d768b44d2f98127aef4cceb17293" dependencies = [ "enumset_derive", ] [[package]] name = "enumset_derive" -version = "0.8.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af" +checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242" dependencies = [ - "darling 0.20.8", + "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -467,9 +488,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if 1.0.0", "libc", @@ -487,9 +508,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash 0.8.11", "allocator-api2", @@ -551,12 +572,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.5" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] @@ -570,9 +591,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "keccak" @@ -585,9 +606,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "leb128" @@ -597,15 +618,15 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -613,18 +634,18 @@ dependencies = [ [[package]] name = "lru" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", ] [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memory_units" @@ -667,9 +688,9 @@ dependencies = [ [[package]] name = "num" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ "num-bigint", "num-complex", @@ -681,20 +702,19 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-complex" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] @@ -707,7 +727,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -721,9 +741,9 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -732,11 +752,10 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", "num-traits", @@ -744,32 +763,32 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "num_enum" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -786,9 +805,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -796,9 +815,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if 1.0.0", "libc", @@ -809,9 +828,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "proc-macro-crate" @@ -848,9 +867,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -865,9 +884,11 @@ version = "0.1.0" dependencies = [ "arbutil", "bincode", + "bitvec", "brotli", "derivative", "digest 0.9.0", + "enum-iterator 2.1.0", "eyre", "fnv", "hex", @@ -918,9 +939,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -957,11 +978,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] @@ -1023,9 +1044,9 @@ checksum = "89dc553bc0cf4512a8b96caa2e21ed5f6e4b66bf28a1bd08fd9eb07c0b39b28c" [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" @@ -1038,9 +1059,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "scopeguard" @@ -1056,37 +1077,38 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -1173,9 +1195,9 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" dependencies = [ "serde", ] @@ -1235,9 +1257,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.52" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -1252,9 +1274,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.14" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "textwrap" @@ -1267,22 +1289,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] [[package]] @@ -1296,9 +1318,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -1311,9 +1333,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" @@ -1321,7 +1343,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.3.0", "toml_datetime", "winnow", ] @@ -1346,9 +1368,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "user-host" @@ -1392,9 +1414,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.7.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" [[package]] name = "vec_map" @@ -1404,9 +1426,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" @@ -1425,9 +1447,9 @@ dependencies = [ [[package]] name = "wasm-encoder" -version = "0.201.0" +version = "0.215.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9c7d2731df60006819b013f64ccc2019691deccf6e11a1804bc850cd6748f1a" +checksum = "4fb56df3e06b8e6b77e37d2969a50ba51281029a9aeb3855e76b7f49b6418847" dependencies = [ "leb128", ] @@ -1437,7 +1459,7 @@ name = "wasmer-types" version = "4.2.8" dependencies = [ "bytecheck", - "enum-iterator", + "enum-iterator 0.7.0", "enumset", "indexmap 1.9.3", "more-asserts", @@ -1452,16 +1474,16 @@ version = "0.121.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab" dependencies = [ - "bitflags 2.5.0", - "indexmap 2.2.5", + "bitflags 2.6.0", + "indexmap 2.3.0", "semver", ] [[package]] name = "wast" -version = "201.0.0" +version = "215.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ef6e1ef34d7da3e2b374fd2b1a9c0227aff6cad596e1b24df9b58d0f6222faa" +checksum = "1ff1d00d893593249e60720be04a7c1f42f1c4dc3806a2869f4e66ab61eb54cb" dependencies = [ "bumpalo", "leb128", @@ -1472,9 +1494,9 @@ dependencies = [ [[package]] name = "wat" -version = "1.201.0" +version = "1.215.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453d5b37a45b98dee4f4cb68015fc73634d7883bbef1c65e6e9c78d454cf3f32" +checksum = "670bf4d9c8cf76ae242d70ded47c546525b6dafaa6871f9bcb065344bf2b4e3d" dependencies = [ "wast", ] @@ -1515,13 +1537,14 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-targets" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -1530,45 +1553,51 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.48.5" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" @@ -1590,20 +1619,20 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.72", ] diff --git a/arbitrator/wasm-testsuite/Cargo.lock b/arbitrator/wasm-testsuite/Cargo.lock index c6f946b8ea..465464479f 100644 --- a/arbitrator/wasm-testsuite/Cargo.lock +++ b/arbitrator/wasm-testsuite/Cargo.lock @@ -4,11 +4,11 @@ version = 3 [[package]] name = "addr2line" -version = "0.19.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ - "gimli 0.27.0", + "gimli 0.29.0", ] [[package]] @@ -19,15 +19,33 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ "getrandom", "once_cell", "version_check", ] +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + [[package]] name = "ansi_term" version = "0.12.1" @@ -41,15 +59,26 @@ dependencies = [ name = "arbutil" version = "0.1.0" dependencies = [ - "sha3 0.10.6", + "digest 0.10.7", + "eyre", + "fnv", + "hex", + "num-traits", + "num_enum", + "ruint2", + "serde", + "sha2 0.10.8", + "sha3 0.10.8", "siphasher", + "tiny-keccak", + "wasmparser", ] [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "atty" @@ -57,26 +86,26 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", @@ -98,6 +127,25 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "serde", + "tap", + "wyz", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -110,9 +158,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] @@ -124,69 +172,92 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] -name = "brotli-sys" -version = "0.3.2" +name = "blst" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" +checksum = "4378725facc195f1a538864863f6de233b500a8862747e7f165078a419d5e874" dependencies = [ "cc", - "libc", + "glob", + "threadpool", + "zeroize", ] [[package]] -name = "brotli2" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" +name = "brotli" +version = "0.1.0" dependencies = [ - "brotli-sys", - "libc", + "lazy_static", + "num_enum", + "wasmer", + "wee_alloc", ] [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytecheck" -version = "0.6.9" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d11cac2c12b5adc6570dad2ee1b87eff4955dac476fe12d81e5fdd352e52406f" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" dependencies = [ "bytecheck_derive", "ptr_meta", + "simdutf8", ] [[package]] name = "bytecheck_derive" -version = "0.6.9" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.3.0" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fca2be1d5c43812bae364ee3f30b3afcb7877cf59f4aeb94c66f313a41d2fac9" + +[[package]] +name = "c-kzg" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +checksum = "94a4bc5367b6284358d2a6a6a1dc2d92ec4b86034561c3b9d3341909752fd848" +dependencies = [ + "blst", + "cc", + "glob", + "hex", + "libc", + "serde", +] [[package]] name = "cc" -version = "1.0.73" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" + +[[package]] +name = "cfg-if" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "cfg-if" @@ -202,44 +273,62 @@ checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "ansi_term", "atty", - "bitflags", + "bitflags 1.3.2", "strsim 0.8.0", "textwrap", "unicode-width", "vec_map", ] +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "corosensei" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9847f90f32a50b0dcbd68bc23ff242798b13080b97b0569f6ed96a45ce4cf2cd" +checksum = "80128832c58ea9cbd041d2a759ec449224487b2c1e400453d99d244eead87a8e" dependencies = [ "autocfg", - "cfg-if", + "cfg-if 1.0.0", "libc", "scopeguard", "windows-sys 0.33.0", ] +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + [[package]] name = "cranelift-bforest" -version = "0.86.1" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529ffacce2249ac60edba2941672dfedf3d96558b415d0d8083cd007456e0f55" +checksum = "2a2ab4512dfd3a6f4be184403a195f76e81a8a9f9e6c898e19d2dc3ce20e0115" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.86.1" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427d105f617efc8cb55f8d036a7fded2e227892d8780b4985e5551f8d27c4a92" +checksum = "98b022ed2a5913a38839dfbafe6cf135342661293b08049843362df4301261dc" dependencies = [ + "arrayvec", + "bumpalo", "cranelift-bforest", "cranelift-codegen-meta", "cranelift-codegen-shared", + "cranelift-egraph", "cranelift-entity", "cranelift-isle", "gimli 0.26.2", @@ -251,30 +340,44 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.86.1" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "551674bed85b838d45358e3eab4f0ffaa6790c70dc08184204b9a54b41cdb7d1" +checksum = "639307b45434ad112a98f8300c0f0ab085cbefcd767efcdef9ef19d4c0756e74" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.86.1" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b3a63ae57498c3eb495360944a33571754241e15e47e3bcae6082f40fec5866" +checksum = "278e52e29c53fcf32431ef08406c295699a70306d05a0715c5b1bf50e33a9ab7" + +[[package]] +name = "cranelift-egraph" +version = "0.91.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624b54323b06e675293939311943ba82d323bb340468ce1889be5da7932c8d73" +dependencies = [ + "cranelift-entity", + "fxhash", + "hashbrown 0.12.3", + "indexmap 1.9.3", + "log", + "smallvec", +] [[package]] name = "cranelift-entity" -version = "0.86.1" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11aa8aa624c72cc1c94ea3d0739fa61248260b5b14d3646f51593a88d67f3e6e" +checksum = "9a59bcbca89c3f1b70b93ab3cbba5e5e0cbf3e63dadb23c7525cb142e21a9d4c" [[package]] name = "cranelift-frontend" -version = "0.86.1" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "544ee8f4d1c9559c9aa6d46e7aaeac4a13856d620561094f35527356c7d21bd0" +checksum = "0d70abacb8cfef3dc8ff7e8836e9c1d70f7967dfdac824a4cd5e30223415aca6" dependencies = [ "cranelift-codegen", "log", @@ -284,54 +387,49 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.86.1" +version = "0.91.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed16b14363d929b8c37e3c557d0a7396791b383ecc302141643c054343170aad" +checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb" [[package]] -name = "crossbeam-channel" -version = "0.5.4" +name = "crossbeam-deque" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", + "crossbeam-epoch", "crossbeam-utils", ] [[package]] -name = "crossbeam-deque" -version = "0.8.1" +name = "crossbeam-epoch" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "cfg-if", - "crossbeam-epoch", "crossbeam-utils", ] [[package]] -name = "crossbeam-epoch" -version = "0.9.8" +name = "crossbeam-queue" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "lazy_static", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" -dependencies = [ - "cfg-if", - "lazy_static", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-common" @@ -355,12 +453,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.14.2" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "darling_core 0.14.2", - "darling_macro 0.14.2", + "darling_core 0.20.10", + "darling_macro 0.20.10", ] [[package]] @@ -374,20 +472,20 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn", + "syn 1.0.109", ] [[package]] name = "darling_core" -version = "0.14.2" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "syn", + "syn 2.0.72", ] [[package]] @@ -398,18 +496,55 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core 0.13.4", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "darling_macro" -version = "0.14.2" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "darling_core 0.14.2", + "darling_core 0.20.10", "quote", - "syn", + "syn 2.0.72", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if 1.0.0", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.72", ] [[package]] @@ -423,11 +558,11 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.3", + "block-buffer 0.10.4", "crypto-common", ] @@ -437,13 +572,13 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "add9a102807b524ec050363f09e06f1504214b0e1c7797f64261c891022dce8b" dependencies = [ - "bitflags", + "bitflags 1.3.2", "byteorder", "lazy_static", "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -454,14 +589,14 @@ checksum = "64fba5a42bd76a17cad4bfa00de168ee1cbfa06a5e8ce992ae880218c05641a9" dependencies = [ "byteorder", "dynasm", - "memmap2", + "memmap2 0.5.10", ] [[package]] name = "either" -version = "1.6.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "enum-iterator" @@ -469,7 +604,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]] @@ -480,35 +624,52 @@ checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" dependencies = [ "proc-macro2", "quote", - "syn", + "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.72", ] [[package]] name = "enumset" -version = "1.0.12" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19be8061a06ab6f3a6cf21106c873578bf01bd42ad15e0311a9c76161cb1c753" +checksum = "d07a4b049558765cef5f0c1a273c3fc57084d768b44d2f98127aef4cceb17293" dependencies = [ "enumset_derive", ] [[package]] name = "enumset_derive" -version = "0.6.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e7b551eba279bf0fa88b83a46330168c1560a52a94f5126f892f0b364ab3e0" +checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242" dependencies = [ - "darling 0.14.2", + "darling 0.20.10", "proc-macro2", "quote", - "syn", + "syn 2.0.72", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "eyre" -version = "0.6.8" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ "indenter", "once_cell", @@ -526,6 +687,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "fxhash" version = "0.2.1" @@ -537,9 +704,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -547,11 +714,11 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi", ] @@ -563,21 +730,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" dependencies = [ "fallible-iterator", - "indexmap", + "indexmap 1.9.3", "stable_deref_trait", ] [[package]] name = "gimli" -version = "0.27.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] -name = "hashbrown" -version = "0.11.2" +name = "glob" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "hashbrown" @@ -585,7 +752,17 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash", + "ahash 0.7.8", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash 0.8.11", + "allocator-api2", ] [[package]] @@ -606,6 +783,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "hex" version = "0.4.3" @@ -626,40 +809,62 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "1.8.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown 0.11.2", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", ] [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] [[package]] name = "keccak" -version = "0.1.0" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "leb128" @@ -669,15 +874,15 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.139" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -685,11 +890,17 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "lru" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" dependencies = [ - "cfg-if", + "hashbrown 0.14.5", ] [[package]] @@ -701,30 +912,54 @@ dependencies = [ "libc", ] +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memmap2" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] [[package]] name = "memmap2" -version = "0.5.8" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" +checksum = "6d28bba84adfe6646737845bc5ebbfa2c08424eb1c37e94a1fd2a82adb56a872" dependencies = [ "libc", ] [[package]] name = "memoffset" -version = "0.6.5" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ "autocfg", ] +[[package]] +name = "memory_units" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -733,9 +968,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] @@ -748,9 +983,9 @@ checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" [[package]] name = "nom" -version = "7.1.1" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", @@ -769,9 +1004,9 @@ dependencies = [ [[package]] name = "num" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ "num-bigint", "num-complex", @@ -783,39 +1018,48 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-complex" -version = "0.4.1" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fbc387afefefd5e9e39493299f3069e14a140dd34dc19b4c1c1a8fddb6a790" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -824,11 +1068,10 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", "num-traits", @@ -836,49 +1079,70 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.72", +] + [[package]] name = "object" -version = "0.30.0" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb" +checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.16.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -886,22 +1150,31 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.5" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", - "windows-sys 0.42.0", + "windows-targets", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "proc-macro-crate" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit", +] [[package]] name = "proc-macro-error" @@ -912,7 +1185,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.109", "version_check", ] @@ -929,11 +1202,11 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.38" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] @@ -942,22 +1215,32 @@ version = "0.1.0" dependencies = [ "arbutil", "bincode", - "brotli2", + "bitvec", + "brotli", + "c-kzg", + "derivative", "digest 0.9.0", + "enum-iterator 2.1.0", "eyre", "fnv", "hex", + "itertools", "lazy_static", "libc", + "lru", "nom", "nom-leb128", "num", + "num-derive", + "num-traits", + "once_cell", "parking_lot", "rayon", "rustc-demangle", "serde", "serde_json", "serde_with", + "sha2 0.9.9", "sha3 0.9.1", "smallvec", "static_assertions", @@ -966,6 +1249,7 @@ dependencies = [ "wasmer-compiler-singlepass", "wasmer-types", "wasmparser", + "wat", ] [[package]] @@ -985,56 +1269,58 @@ checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "quote" -version = "1.0.18" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rayon" -version = "1.5.2" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd249e82c21598a9a426a4e00dd7adc1d640b22445ec8545feef801d1a74c221" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ - "autocfg", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags", + "bitflags 2.6.0", ] [[package]] name = "regalloc2" -version = "0.3.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d43a209257d978ef079f3d446331d0f1794f5e0fc19b306a199983857833a779" +checksum = "300d4fbfb40c1c66a78ba3ddd41c1110247cf52f97b87d0f2fc9209bd49b030c" dependencies = [ "fxhash", "log", @@ -1044,74 +1330,99 @@ dependencies = [ [[package]] name = "region" -version = "3.0.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" +checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7" dependencies = [ - "bitflags", + "bitflags 1.3.2", "libc", - "mach", - "winapi", + "mach2", + "windows-sys 0.52.0", ] [[package]] name = "rend" -version = "0.3.6" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" dependencies = [ "bytecheck", ] [[package]] name = "rkyv" -version = "0.7.39" +version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15" +checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" dependencies = [ + "bitvec", "bytecheck", + "bytes", "hashbrown 0.12.3", - "indexmap", + "indexmap 1.9.3", "ptr_meta", "rend", "rkyv_derive", "seahash", + "tinyvec", + "uuid", ] [[package]] name = "rkyv_derive" -version = "0.7.39" +version = "0.7.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4" +checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] +[[package]] +name = "ruint2" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b066b8e4fcea7fae86b6932d2449670b6b5545b7e8407841b2d3a916ff2a9f86" +dependencies = [ + "derive_more", + "ruint2-macro", + "rustc_version", + "thiserror", +] + +[[package]] +name = "ruint2-macro" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89dc553bc0cf4512a8b96caa2e21ed5f6e4b66bf28a1bd08fd9eb07c0b39b28c" + [[package]] name = "rustc-demangle" -version = "0.1.21" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] -name = "rustversion" -version = "1.0.6" +name = "rustc_version" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "seahash" @@ -1119,11 +1430,23 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "self_cell" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + [[package]] name = "serde" -version = "1.0.137" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] @@ -1141,33 +1464,33 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.72", ] [[package]] name = "serde_json" -version = "1.0.81" +version = "1.0.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_with" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b827f2113224f3f19a665136f006709194bdfdcb1fdc1e4b2b5cbac8e0cced54" +checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" dependencies = [ - "rustversion", "serde", "serde_with_macros", ] @@ -1181,7 +1504,31 @@ dependencies = [ "darling 0.13.4", "proc-macro2", "quote", - "syn", + "syn 1.0.109", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.7", ] [[package]] @@ -1198,31 +1545,47 @@ dependencies = [ [[package]] name = "sha3" -version = "0.10.6" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "keccak", ] +[[package]] +name = "shared-buffer" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6c99835bad52957e7aa241d3975ed17c1e5f8c92026377d117a606f36b84b16" +dependencies = [ + "bytes", + "memmap2 0.6.2", +] + +[[package]] +name = "simdutf8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" + [[package]] name = "siphasher" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "slice-group-by" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b634d87b960ab1a38c4fe143b508576f075e7c978bfad18217645ebfdfa2ec" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] name = "smallvec" -version = "1.10.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" dependencies = [ "serde", ] @@ -1272,25 +1635,42 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] name = "syn" -version = "1.0.94" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a07e33e919ebcd69113d5be0e4d70c5707004ff45188910106854f38b960df4a" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "target-lexicon" -version = "0.12.5" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "textwrap" @@ -1303,31 +1683,80 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.38" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.38" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.72", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.3.0", + "toml_datetime", + "winnow", ] [[package]] name = "tracing" -version = "0.1.36" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -1335,47 +1764,53 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.22" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.72", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", ] [[package]] name = "typenum" -version = "1.15.0" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-segmentation" -version = "1.9.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] -name = "unicode-xid" -version = "0.2.3" +name = "uuid" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" [[package]] name = "vec_map" @@ -1385,9 +1820,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" @@ -1397,57 +1832,34 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn", + "syn 2.0.72", "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-downcast" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dac026d43bcca6e7ce1c0956ba68f59edf6403e8e930a5d891be72c31a44340" -dependencies = [ - "js-sys", - "once_cell", - "wasm-bindgen", - "wasm-bindgen-downcast-macros", -] - -[[package]] -name = "wasm-bindgen-downcast-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5020cfa87c7cecefef118055d44e3c1fc122c7ec25701d528ee458a0b45f38f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1455,28 +1867,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.72", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasm-encoder" -version = "0.20.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05632e0a66a6ed8cca593c24223aabd6262f256c3693ad9822c315285f010614" +checksum = "1ba64e81215916eaeb48fee292f29401d69235d62d8b8fd92a7b2844ec5ae5f7" dependencies = [ "leb128", ] @@ -1496,19 +1908,22 @@ dependencies = [ [[package]] name = "wasmer" -version = "3.1.0" +version = "4.2.8" dependencies = [ "bytes", - "cfg-if", - "indexmap", + "cfg-if 1.0.0", + "derivative", + "indexmap 1.9.3", "js-sys", "more-asserts", + "rustc-demangle", "serde", "serde-wasm-bindgen", + "shared-buffer", "target-lexicon", "thiserror", + "tracing", "wasm-bindgen", - "wasm-bindgen-downcast", "wasmer-compiler", "wasmer-compiler-cranelift", "wasmer-derive", @@ -1520,18 +1935,21 @@ dependencies = [ [[package]] name = "wasmer-compiler" -version = "3.1.0" +version = "4.2.8" dependencies = [ "backtrace", - "cfg-if", - "enum-iterator", + "bytes", + "cfg-if 1.0.0", + "enum-iterator 0.7.0", "enumset", "lazy_static", "leb128", - "memmap2", + "memmap2 0.5.10", "more-asserts", "region", - "rustc-demangle", + "rkyv", + "self_cell", + "shared-buffer", "smallvec", "thiserror", "wasmer-types", @@ -1542,7 +1960,7 @@ dependencies = [ [[package]] name = "wasmer-compiler-cranelift" -version = "3.1.0" +version = "4.2.8" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -1559,7 +1977,7 @@ dependencies = [ [[package]] name = "wasmer-compiler-singlepass" -version = "3.1.0" +version = "4.2.8" dependencies = [ "byteorder", "dynasm", @@ -1576,21 +1994,22 @@ dependencies = [ [[package]] name = "wasmer-derive" -version = "3.1.0" +version = "4.2.8" dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "wasmer-types" -version = "3.1.0" +version = "4.2.8" dependencies = [ - "enum-iterator", + "bytecheck", + "enum-iterator 0.7.0", "enumset", - "indexmap", + "indexmap 1.9.3", "more-asserts", "rkyv", "target-lexicon", @@ -1599,14 +2018,18 @@ dependencies = [ [[package]] name = "wasmer-vm" -version = "3.1.0" +version = "4.2.8" dependencies = [ "backtrace", "cc", - "cfg-if", + "cfg-if 1.0.0", "corosensei", - "enum-iterator", - "indexmap", + "crossbeam-queue", + "dashmap", + "derivative", + "enum-iterator 0.7.0", + "fnv", + "indexmap 1.9.3", "lazy_static", "libc", "mach", @@ -1621,15 +2044,20 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.83.0" +version = "0.121.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a" +checksum = "9dbe55c8f9d0dbd25d9447a5a889ff90c0cc3feaa7395310d3d826b2c703eaab" +dependencies = [ + "bitflags 2.6.0", + "indexmap 2.3.0", + "semver", +] [[package]] name = "wast" -version = "50.0.0" +version = "64.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2cbb59d4ac799842791fe7e806fa5dbbf6b5554d538e51cc8e176db6ff0ae34" +checksum = "a259b226fd6910225aa7baeba82f9d9933b6d00f2ce1b49b80fa4214328237cc" dependencies = [ "leb128", "memchr", @@ -1639,13 +2067,25 @@ dependencies = [ [[package]] name = "wat" -version = "1.0.52" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "584aaf7a1ecf4d383bbe1a25eeab0cbb8ff96acc6796707ff65cde48f4632f15" +checksum = "53253d920ab413fca1c7dc2161d601c79b4fdf631d0ba51dd4343bf9b556c3f6" dependencies = [ "wast", ] +[[package]] +name = "wee_alloc" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb3b5a6b2bb17cb6ad44a2e68a43e8d2722c997da10e928665c72ec6c0a0b8e" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "memory_units", + "winapi", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1683,24 +2123,34 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.0", + "windows_x86_64_msvc 0.52.6", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -1710,9 +2160,9 @@ checksum = "cd761fd3eb9ab8cc1ed81e56e567f02dd82c4c837e48ac3b2181b9ffc5060807" [[package]] name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -1722,9 +2172,15 @@ checksum = "cab0cf703a96bab2dc0c02c0fa748491294bf9b7feb27e1f4f96340f208ada0e" [[package]] name = "windows_i686_gnu" -version = "0.42.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -1734,9 +2190,9 @@ checksum = "8cfdbe89cc9ad7ce618ba34abc34bbb6c36d99e96cae2245b7943cd75ee773d0" [[package]] name = "windows_i686_msvc" -version = "0.42.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -1746,15 +2202,15 @@ checksum = "b4dd9b0c0e9ece7bb22e84d70d01b71c6d6248b81a3c60d11869451b4cb24784" [[package]] name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -1764,6 +2220,64 @@ checksum = "ff1e4aa646495048ec7f3ffddc411e1d829c026a2ec62b39da15c1055e406eaa" [[package]] name = "windows_x86_64_msvc" -version = "0.42.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index ccf9b4aab7..965f6c2695 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -238,7 +238,7 @@ var DefaultBatchPosterConfig = BatchPosterConfig{ MaxDelay: time.Hour, WaitForMaxDelay: false, CompressionLevel: brotli.BestCompression, - DASRetentionPeriod: time.Hour * 24 * 15, + DASRetentionPeriod: daprovider.DefaultDASRetentionPeriod, GasRefunderAddress: "", ExtraBatchGas: 50_000, Post4844Blobs: false, @@ -270,7 +270,7 @@ var TestBatchPosterConfig = BatchPosterConfig{ MaxDelay: 0, WaitForMaxDelay: false, CompressionLevel: 2, - DASRetentionPeriod: time.Hour * 24 * 15, + DASRetentionPeriod: daprovider.DefaultDASRetentionPeriod, GasRefunderAddress: "", ExtraBatchGas: 10_000, Post4844Blobs: true, diff --git a/arbnode/dataposter/data_poster.go b/arbnode/dataposter/data_poster.go index ebb5b086cd..15446fe855 100644 --- a/arbnode/dataposter/data_poster.go +++ b/arbnode/dataposter/data_poster.go @@ -28,6 +28,7 @@ import ( "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" @@ -50,6 +51,14 @@ import ( redisstorage "github.com/offchainlabs/nitro/arbnode/dataposter/redis" ) +var ( + latestFinalizedNonceGauge = metrics.NewRegisteredGauge("arb/dataposter/nonce/finalized", nil) + latestSoftConfirmedNonceGauge = metrics.NewRegisteredGauge("arb/dataposter/nonce/softconfirmed", nil) + latestUnconfirmedNonceGauge = metrics.NewRegisteredGauge("arb/dataposter/nonce/unconfirmed", nil) + totalQueueLengthGauge = metrics.NewRegisteredGauge("arb/dataposter/queue/length", nil) + totalQueueWeightGauge = metrics.NewRegisteredGauge("arb/dataposter/queue/weight", nil) +) + // Dataposter implements functionality to post transactions on the chain. It // is initialized with specified sender/signer and keeps nonce of that address // as it posts transactions. @@ -350,6 +359,7 @@ func (p *DataPoster) canPostWithNonce(ctx context.Context, nextNonce uint64, thi if err != nil { return fmt.Errorf("getting nonce of a dataposter sender: %w", err) } + latestUnconfirmedNonceGauge.Update(int64(unconfirmedNonce)) if nextNonce >= cfg.MaxMempoolTransactions+unconfirmedNonce { return fmt.Errorf("%w: transaction nonce: %d, unconfirmed nonce: %d, max mempool size: %d", ErrExceedsMaxMempoolSize, nextNonce, unconfirmedNonce, cfg.MaxMempoolTransactions) } @@ -361,6 +371,7 @@ func (p *DataPoster) canPostWithNonce(ctx context.Context, nextNonce uint64, thi if err != nil { return fmt.Errorf("getting nonce of a dataposter sender: %w", err) } + latestUnconfirmedNonceGauge.Update(int64(unconfirmedNonce)) if unconfirmedNonce > nextNonce { return fmt.Errorf("latest on-chain nonce %v is greater than to next nonce %v", unconfirmedNonce, nextNonce) } @@ -514,6 +525,7 @@ func (p *DataPoster) feeAndTipCaps(ctx context.Context, nonce uint64, gasLimit u if err != nil { return nil, nil, nil, fmt.Errorf("failed to get latest nonce %v blocks ago (block %v): %w", config.NonceRbfSoftConfs, softConfBlock, err) } + latestSoftConfirmedNonceGauge.Update(int64(softConfNonce)) suggestedTip, err := p.client.SuggestGasTipCap(ctx) if err != nil { @@ -1040,6 +1052,7 @@ func (p *DataPoster) updateNonce(ctx context.Context) error { } return nil } + latestFinalizedNonceGauge.Update(int64(nonce)) log.Info("Data poster transactions confirmed", "previousNonce", p.nonce, "newNonce", nonce, "previousL1Block", p.lastBlock, "newL1Block", header.Number) if len(p.errorCount) > 0 { for x := p.nonce; x < nonce; x++ { @@ -1119,6 +1132,7 @@ func (p *DataPoster) Start(ctxIn context.Context) { log.Warn("Failed to get latest nonce", "err", err) return minWait } + latestUnconfirmedNonceGauge.Update(int64(unconfirmedNonce)) // We use unconfirmedNonce here to replace-by-fee transactions that aren't in a block, // excluding those that are in an unconfirmed block. If a reorg occurs, we'll continue // replacing them by fee. @@ -1136,13 +1150,24 @@ func (p *DataPoster) Start(ctxIn context.Context) { if latestQueued != nil { latestCumulativeWeight = latestQueued.CumulativeWeight() latestNonce = latestQueued.FullTx.Nonce() + + confirmedNonce := unconfirmedNonce - 1 + confirmedMeta, err := p.queue.Get(ctx, confirmedNonce) + if err == nil && confirmedMeta != nil { + totalQueueWeightGauge.Update(int64(arbmath.SaturatingUSub(latestCumulativeWeight, confirmedMeta.CumulativeWeight()))) + totalQueueLengthGauge.Update(int64(arbmath.SaturatingUSub(latestNonce, confirmedNonce))) + } else { + log.Error("Failed to fetch latest confirmed tx from queue", "err", err, "confirmedMeta", confirmedMeta) + } + } + for _, tx := range queueContents { previouslyUnsent := !tx.Sent sendAttempted := false if now.After(tx.NextReplacement) { - nonceBacklog := arbmath.SaturatingUSub(latestNonce, tx.FullTx.Nonce()) weightBacklog := arbmath.SaturatingUSub(latestCumulativeWeight, tx.CumulativeWeight()) + nonceBacklog := arbmath.SaturatingUSub(latestNonce, tx.FullTx.Nonce()) err := p.replaceTx(ctx, tx, arbmath.MaxInt(nonceBacklog, weightBacklog)) sendAttempted = true p.maybeLogError(err, tx, "failed to replace-by-fee transaction") diff --git a/arbnode/dataposter/dataposter_test.go b/arbnode/dataposter/dataposter_test.go index 0c621384ba..7f2f61c07e 100644 --- a/arbnode/dataposter/dataposter_test.go +++ b/arbnode/dataposter/dataposter_test.go @@ -177,6 +177,10 @@ func (c *stubL1Client) CallContractAtHash(ctx context.Context, msg ethereum.Call return []byte{}, nil } +func (c *stubL1Client) CodeAtHash(ctx context.Context, address common.Address, blockHash common.Hash) ([]byte, error) { + return []byte{}, nil +} + func (c *stubL1Client) ChainID(ctx context.Context) (*big.Int, error) { return nil, nil } diff --git a/arbnode/dataposter/dbstorage/storage.go b/arbnode/dataposter/dbstorage/storage.go index 2cfda5d779..97055193a6 100644 --- a/arbnode/dataposter/dbstorage/storage.go +++ b/arbnode/dataposter/dbstorage/storage.go @@ -7,15 +7,12 @@ import ( "bytes" "context" "encoding/hex" - "errors" "fmt" "strconv" - "github.com/cockroachdb/pebble" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/ethdb/memorydb" "github.com/offchainlabs/nitro/arbnode/dataposter/storage" - "github.com/syndtr/goleveldb/leveldb" + "github.com/offchainlabs/nitro/util/dbutil" ) // Storage implements db based storage for batch poster. @@ -62,7 +59,7 @@ func (s *Storage) Get(_ context.Context, index uint64) (*storage.QueuedTransacti key := idxToKey(index) value, err := s.db.Get(key) if err != nil { - if errors.Is(err, leveldb.ErrNotFound) { + if dbutil.IsErrNotFound(err) { return nil, nil } return nil, err @@ -134,7 +131,7 @@ func (s *Storage) Prune(ctx context.Context, until uint64) error { func (s *Storage) valueAt(_ context.Context, key []byte) ([]byte, error) { val, err := s.db.Get(key) if err != nil { - if isErrNotFound(err) { + if dbutil.IsErrNotFound(err) { return s.encDec().Encode((*storage.QueuedTransaction)(nil)) } return nil, err @@ -168,10 +165,10 @@ func (s *Storage) Put(ctx context.Context, index uint64, prev, new *storage.Queu return fmt.Errorf("updating value at: %v: %w", key, err) } lastItemIdx, err := s.lastItemIdx(ctx) - if err != nil && !isErrNotFound(err) { + if err != nil && !dbutil.IsErrNotFound(err) { return err } - if isErrNotFound(err) { + if dbutil.IsErrNotFound(err) { lastItemIdx = []byte{} } if cnt == 0 || bytes.Compare(key, lastItemIdx) > 0 { @@ -188,7 +185,7 @@ func (s *Storage) Put(ctx context.Context, index uint64, prev, new *storage.Queu func (s *Storage) Length(context.Context) (int, error) { val, err := s.db.Get(countKey) if err != nil { - if isErrNotFound(err) { + if dbutil.IsErrNotFound(err) { return 0, nil } return 0, err @@ -199,7 +196,3 @@ func (s *Storage) Length(context.Context) (int, error) { func (s *Storage) IsPersistent() bool { return true } - -func isErrNotFound(err error) bool { - return errors.Is(err, leveldb.ErrNotFound) || errors.Is(err, pebble.ErrNotFound) || errors.Is(err, memorydb.ErrMemorydbNotFound) -} diff --git a/arbnode/delayed_sequencer.go b/arbnode/delayed_sequencer.go index 8cbb094c16..4f18531a76 100644 --- a/arbnode/delayed_sequencer.go +++ b/arbnode/delayed_sequencer.go @@ -26,6 +26,7 @@ type DelayedSequencer struct { l1Reader *headerreader.HeaderReader bridge *DelayedBridge inbox *InboxTracker + reader *InboxReader exec execution.ExecutionSequencer coordinator *SeqCoordinator waitingForFinalizedBlock uint64 @@ -68,6 +69,7 @@ func NewDelayedSequencer(l1Reader *headerreader.HeaderReader, reader *InboxReade l1Reader: l1Reader, bridge: reader.DelayedBridge(), inbox: reader.Tracker(), + reader: reader, coordinator: coordinator, exec: exec, config: config, @@ -144,7 +146,7 @@ func (d *DelayedSequencer) sequenceWithoutLockout(ctx context.Context, lastBlock var lastDelayedAcc common.Hash var messages []*arbostypes.L1IncomingMessage for pos < dbDelayedCount { - msg, acc, parentChainBlockNumber, err := d.inbox.GetDelayedMessageAccumulatorAndParentChainBlockNumber(pos) + msg, acc, parentChainBlockNumber, err := d.inbox.GetDelayedMessageAccumulatorAndParentChainBlockNumber(ctx, pos) if err != nil { return err } @@ -165,6 +167,13 @@ func (d *DelayedSequencer) sequenceWithoutLockout(ctx context.Context, lastBlock } } lastDelayedAcc = acc + err = msg.FillInBatchGasCost(func(batchNum uint64) ([]byte, error) { + data, _, err := d.reader.GetSequencerMessageBytes(ctx, batchNum) + return data, err + }) + if err != nil { + return err + } messages = append(messages, msg) pos++ } diff --git a/arbnode/inbox_reader.go b/arbnode/inbox_reader.go index 78b4db1929..77a0b6e7a2 100644 --- a/arbnode/inbox_reader.go +++ b/arbnode/inbox_reader.go @@ -143,7 +143,11 @@ func (r *InboxReader) Start(ctxIn context.Context) error { break } // Validate the init message matches our L2 blockchain - message, err := r.tracker.GetDelayedMessage(0) + ctx, err := r.StopWaiter.GetContextSafe() + if err != nil { + return err + } + message, err := r.tracker.GetDelayedMessage(ctx, 0) if err != nil { return err } @@ -226,7 +230,7 @@ func (r *InboxReader) CaughtUp() chan struct{} { func (r *InboxReader) run(ctx context.Context, hadError bool) error { readMode := r.config().ReadMode - from, err := r.getNextBlockToRead() + from, err := r.getNextBlockToRead(ctx) if err != nil { return err } @@ -584,7 +588,7 @@ func (r *InboxReader) getPrevBlockForReorg(from *big.Int) (*big.Int, error) { return newFrom, nil } -func (r *InboxReader) getNextBlockToRead() (*big.Int, error) { +func (r *InboxReader) getNextBlockToRead(ctx context.Context) (*big.Int, error) { delayedCount, err := r.tracker.GetDelayedCount() if err != nil { return nil, err @@ -592,7 +596,7 @@ func (r *InboxReader) getNextBlockToRead() (*big.Int, error) { if delayedCount == 0 { return new(big.Int).Set(r.firstMessageBlock), nil } - _, _, parentChainBlockNumber, err := r.tracker.GetDelayedMessageAccumulatorAndParentChainBlockNumber(delayedCount - 1) + _, _, parentChainBlockNumber, err := r.tracker.GetDelayedMessageAccumulatorAndParentChainBlockNumber(ctx, delayedCount-1) if err != nil { return nil, err } 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/inbox_tracker.go b/arbnode/inbox_tracker.go index b950c1e1ef..23b81bde62 100644 --- a/arbnode/inbox_tracker.go +++ b/arbnode/inbox_tracker.go @@ -300,7 +300,7 @@ func (t *InboxTracker) PopulateFeedBacklog(broadcastServer *broadcaster.Broadcas return fmt.Errorf("error getting message %v: %w", seqNum, err) } - msgResult, err := t.txStreamer.ResultAtCount(seqNum) + msgResult, err := t.txStreamer.ResultAtCount(seqNum + 1) var blockHash *common.Hash if err == nil { blockHash = &msgResult.BlockHash @@ -316,7 +316,7 @@ func (t *InboxTracker) PopulateFeedBacklog(broadcastServer *broadcaster.Broadcas return nil } -func (t *InboxTracker) legacyGetDelayedMessageAndAccumulator(seqNum uint64) (*arbostypes.L1IncomingMessage, common.Hash, error) { +func (t *InboxTracker) legacyGetDelayedMessageAndAccumulator(ctx context.Context, seqNum uint64) (*arbostypes.L1IncomingMessage, common.Hash, error) { key := dbKey(legacyDelayedMessagePrefix, seqNum) data, err := t.db.Get(key) if err != nil { @@ -328,17 +328,26 @@ func (t *InboxTracker) legacyGetDelayedMessageAndAccumulator(seqNum uint64) (*ar var acc common.Hash copy(acc[:], data[:32]) msg, err := arbostypes.ParseIncomingL1Message(bytes.NewReader(data[32:]), nil) + if err != nil { + return nil, common.Hash{}, err + } + + err = msg.FillInBatchGasCost(func(batchNum uint64) ([]byte, error) { + data, _, err := t.txStreamer.inboxReader.GetSequencerMessageBytes(ctx, batchNum) + return data, err + }) + return msg, acc, err } -func (t *InboxTracker) GetDelayedMessageAccumulatorAndParentChainBlockNumber(seqNum uint64) (*arbostypes.L1IncomingMessage, common.Hash, uint64, error) { +func (t *InboxTracker) GetDelayedMessageAccumulatorAndParentChainBlockNumber(ctx context.Context, seqNum uint64) (*arbostypes.L1IncomingMessage, common.Hash, uint64, error) { delayedMessageKey := dbKey(rlpDelayedMessagePrefix, seqNum) exists, err := t.db.Has(delayedMessageKey) if err != nil { return nil, common.Hash{}, 0, err } if !exists { - msg, acc, err := t.legacyGetDelayedMessageAndAccumulator(seqNum) + msg, acc, err := t.legacyGetDelayedMessageAndAccumulator(ctx, seqNum) return msg, acc, 0, err } data, err := t.db.Get(delayedMessageKey) @@ -356,6 +365,14 @@ func (t *InboxTracker) GetDelayedMessageAccumulatorAndParentChainBlockNumber(seq return msg, acc, 0, err } + err = msg.FillInBatchGasCost(func(batchNum uint64) ([]byte, error) { + data, _, err := t.txStreamer.inboxReader.GetSequencerMessageBytes(ctx, batchNum) + return data, err + }) + if err != nil { + return msg, acc, 0, err + } + parentChainBlockNumberKey := dbKey(parentChainBlockNumberPrefix, seqNum) exists, err = t.db.Has(parentChainBlockNumberKey) if err != nil { @@ -373,13 +390,13 @@ func (t *InboxTracker) GetDelayedMessageAccumulatorAndParentChainBlockNumber(seq } -func (t *InboxTracker) GetDelayedMessage(seqNum uint64) (*arbostypes.L1IncomingMessage, error) { - msg, _, _, err := t.GetDelayedMessageAccumulatorAndParentChainBlockNumber(seqNum) +func (t *InboxTracker) GetDelayedMessage(ctx context.Context, seqNum uint64) (*arbostypes.L1IncomingMessage, error) { + msg, _, _, err := t.GetDelayedMessageAccumulatorAndParentChainBlockNumber(ctx, seqNum) return msg, err } -func (t *InboxTracker) GetDelayedMessageBytes(seqNum uint64) ([]byte, error) { - msg, err := t.GetDelayedMessage(seqNum) +func (t *InboxTracker) GetDelayedMessageBytes(ctx context.Context, seqNum uint64) ([]byte, error) { + msg, err := t.GetDelayedMessage(ctx, seqNum) if err != nil { return nil, err } @@ -617,7 +634,7 @@ func (b *multiplexerBackend) ReadDelayedInbox(seqNum uint64) (*arbostypes.L1Inco if len(b.batches) == 0 || seqNum >= b.batches[0].AfterDelayedCount { return nil, errors.New("attempted to read past end of sequencer batch delayed messages") } - return b.inbox.GetDelayedMessage(seqNum) + return b.inbox.GetDelayedMessage(b.ctx, seqNum) } var delayedMessagesMismatch = errors.New("sequencer batch delayed messages missing or different") diff --git a/arbnode/message_pruner.go b/arbnode/message_pruner.go index 5d18341a27..e1bc72632b 100644 --- a/arbnode/message_pruner.go +++ b/arbnode/message_pruner.go @@ -30,6 +30,7 @@ type MessagePruner struct { lastPruneDone time.Time cachedPrunedMessages uint64 cachedPrunedBlockHashesInputFeed uint64 + cachedPrunedMessageResult uint64 cachedPrunedDelayedMessages uint64 } @@ -116,7 +117,15 @@ func (m *MessagePruner) prune(ctx context.Context, count arbutil.MessageIndex, g } func (m *MessagePruner) deleteOldMessagesFromDB(ctx context.Context, messageCount arbutil.MessageIndex, delayedMessageCount uint64) error { - prunedKeysRange, err := deleteFromLastPrunedUptoEndKey(ctx, m.transactionStreamer.db, blockHashInputFeedPrefix, &m.cachedPrunedBlockHashesInputFeed, uint64(messageCount)) + prunedKeysRange, err := deleteFromLastPrunedUptoEndKey(ctx, m.transactionStreamer.db, messageResultPrefix, &m.cachedPrunedMessageResult, uint64(messageCount)) + if err != nil { + return fmt.Errorf("error deleting message results: %w", err) + } + if len(prunedKeysRange) > 0 { + log.Info("Pruned message results:", "first pruned key", prunedKeysRange[0], "last pruned key", prunedKeysRange[len(prunedKeysRange)-1]) + } + + prunedKeysRange, err = deleteFromLastPrunedUptoEndKey(ctx, m.transactionStreamer.db, blockHashInputFeedPrefix, &m.cachedPrunedBlockHashesInputFeed, uint64(messageCount)) if err != nil { return fmt.Errorf("error deleting expected block hashes: %w", err) } diff --git a/arbnode/message_pruner_test.go b/arbnode/message_pruner_test.go index ed85c0ebce..e64bb4f838 100644 --- a/arbnode/message_pruner_test.go +++ b/arbnode/message_pruner_test.go @@ -23,6 +23,7 @@ func TestMessagePrunerWithPruningEligibleMessagePresent(t *testing.T) { checkDbKeys(t, messagesCount, transactionStreamerDb, messagePrefix) checkDbKeys(t, messagesCount, transactionStreamerDb, blockHashInputFeedPrefix) + checkDbKeys(t, messagesCount, transactionStreamerDb, messageResultPrefix) checkDbKeys(t, messagesCount, inboxTrackerDb, rlpDelayedMessagePrefix) } @@ -72,8 +73,8 @@ func TestMessagePrunerWithNoPruningEligibleMessagePresent(t *testing.T) { checkDbKeys(t, uint64(messagesCount), transactionStreamerDb, messagePrefix) checkDbKeys(t, uint64(messagesCount), transactionStreamerDb, blockHashInputFeedPrefix) + checkDbKeys(t, uint64(messagesCount), transactionStreamerDb, messageResultPrefix) checkDbKeys(t, messagesCount, inboxTrackerDb, rlpDelayedMessagePrefix) - } func setupDatabase(t *testing.T, messageCount, delayedMessageCount uint64) (ethdb.Database, ethdb.Database, *MessagePruner) { @@ -83,6 +84,8 @@ func setupDatabase(t *testing.T, messageCount, delayedMessageCount uint64) (ethd Require(t, err) err = transactionStreamerDb.Put(dbKey(blockHashInputFeedPrefix, i), []byte{}) Require(t, err) + err = transactionStreamerDb.Put(dbKey(messageResultPrefix, i), []byte{}) + Require(t, err) } inboxTrackerDb := rawdb.NewMemoryDatabase() diff --git a/arbnode/node.go b/arbnode/node.go index a2ccdd1834..e235ef9839 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, @@ -990,10 +990,6 @@ func (n *Node) StopAndWait() { } } -func (n *Node) FetchBatch(ctx context.Context, batchNum uint64) ([]byte, common.Hash, error) { - return n.InboxReader.GetSequencerMessageBytes(ctx, batchNum) -} - func (n *Node) FindInboxBatchContainingMessage(message arbutil.MessageIndex) (uint64, bool, error) { return n.InboxTracker.FindInboxBatchContainingMessage(message) } diff --git a/arbnode/schema.go b/arbnode/schema.go index 2854b7e785..1aaded2b95 100644 --- a/arbnode/schema.go +++ b/arbnode/schema.go @@ -6,6 +6,7 @@ package arbnode var ( messagePrefix []byte = []byte("m") // maps a message sequence number to a message blockHashInputFeedPrefix []byte = []byte("b") // maps a message sequence number to a block hash received through the input feed + messageResultPrefix []byte = []byte("r") // maps a message sequence number to a message result legacyDelayedMessagePrefix []byte = []byte("d") // maps a delayed sequence number to an accumulator and a message as serialized on L1 rlpDelayedMessagePrefix []byte = []byte("e") // maps a delayed sequence number to an accumulator and an RLP encoded message parentChainBlockNumberPrefix []byte = []byte("p") // maps a delayed sequence number to a parent chain block number diff --git a/arbnode/transaction_streamer.go b/arbnode/transaction_streamer.go index 22ecdd553c..90e7feddc6 100644 --- a/arbnode/transaction_streamer.go +++ b/arbnode/transaction_streamer.go @@ -19,9 +19,7 @@ import ( "errors" - "github.com/cockroachdb/pebble" flag "github.com/spf13/pflag" - "github.com/syndtr/goleveldb/leveldb" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethdb" @@ -36,6 +34,7 @@ import ( "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/util/arbmath" + "github.com/offchainlabs/nitro/util/dbutil" "github.com/offchainlabs/nitro/util/sharedmetrics" "github.com/offchainlabs/nitro/util/stopwaiter" ) @@ -130,7 +129,8 @@ type blockHashDBValue struct { } const ( - BlockHashMismatchLogMsg = "BlockHash from feed doesn't match locally computed hash. Check feed source." + BlockHashMismatchLogMsg = "BlockHash from feed doesn't match locally computed hash. Check feed source." + FailedToGetMsgResultFromDB = "Reading message result remotely." ) // Encodes a uint64 as bytes in a lexically sortable manner for database iteration. @@ -374,6 +374,10 @@ func (s *TransactionStreamer) reorg(batch ethdb.Batch, count arbutil.MessageInde } } + err = deleteStartingAt(s.db, batch, messageResultPrefix, uint64ToKey(uint64(count))) + if err != nil { + return err + } err = deleteStartingAt(s.db, batch, blockHashInputFeedPrefix, uint64ToKey(uint64(count))) if err != nil { return err @@ -383,6 +387,14 @@ func (s *TransactionStreamer) reorg(batch ethdb.Batch, count arbutil.MessageInde return err } + for i := 0; i < len(messagesResults); i++ { + pos := count + arbutil.MessageIndex(i) + err = s.storeResult(pos, *messagesResults[i], batch) + if err != nil { + return err + } + } + return setMessageCount(batch, count) } @@ -407,10 +419,6 @@ func dbKey(prefix []byte, pos uint64) []byte { return key } -func isErrNotFound(err error) bool { - return errors.Is(err, leveldb.ErrNotFound) || errors.Is(err, pebble.ErrNotFound) -} - // Note: if changed to acquire the mutex, some internal users may need to be updated to a non-locking version. func (s *TransactionStreamer) GetMessage(seqNum arbutil.MessageIndex) (*arbostypes.MessageWithMetadata, error) { key := dbKey(messagePrefix, uint64(seqNum)) @@ -424,6 +432,18 @@ func (s *TransactionStreamer) GetMessage(seqNum arbutil.MessageIndex) (*arbostyp return nil, err } + err = message.Message.FillInBatchGasCost(func(batchNum uint64) ([]byte, error) { + ctx, err := s.GetContextSafe() + if err != nil { + return nil, err + } + data, _, err := s.inboxReader.GetSequencerMessageBytes(ctx, batchNum) + return data, err + }) + if err != nil { + return nil, err + } + return &message, nil } @@ -446,7 +466,7 @@ func (s *TransactionStreamer) getMessageWithMetadataAndBlockHash(seqNum arbutil. return nil, err } blockHash = blockHashDBVal.BlockHash - } else if !isErrNotFound(err) { + } else if !dbutil.IsErrNotFound(err) { return nil, err } @@ -592,7 +612,7 @@ func (s *TransactionStreamer) AddBroadcastMessages(feedMessages []*m.BroadcastFe if broadcastStartPos > 0 { _, err := s.GetMessage(broadcastStartPos - 1) if err != nil { - if !isErrNotFound(err) { + if !dbutil.IsErrNotFound(err) { return err } // Message before current message doesn't exist in database, so don't add current messages yet @@ -1046,12 +1066,43 @@ func (s *TransactionStreamer) writeMessages(pos arbutil.MessageIndex, messages [ return nil } -// TODO: eventually there will be a table maintained by txStreamer itself func (s *TransactionStreamer) ResultAtCount(count arbutil.MessageIndex) (*execution.MessageResult, error) { if count == 0 { return &execution.MessageResult{}, nil } - return s.exec.ResultAtPos(count - 1) + pos := count - 1 + + key := dbKey(messageResultPrefix, uint64(pos)) + data, err := s.db.Get(key) + if err == nil { + var msgResult execution.MessageResult + err = rlp.DecodeBytes(data, &msgResult) + if err == nil { + return &msgResult, nil + } + } else if !dbutil.IsErrNotFound(err) { + return nil, err + } + log.Info(FailedToGetMsgResultFromDB, "count", count) + + msgResult, err := s.exec.ResultAtPos(pos) + if err != nil { + return nil, err + } + // Stores result in Consensus DB in a best-effort manner + batch := s.db.NewBatch() + err = s.storeResult(pos, *msgResult, batch) + if err != nil { + log.Warn("Failed to store result at ResultAtCount", "err", err) + return msgResult, nil + } + err = batch.Write() + if err != nil { + log.Warn("Failed to store result at ResultAtCount", "err", err) + return msgResult, nil + } + + return msgResult, nil } func (s *TransactionStreamer) checkResult(msgResult *execution.MessageResult, expectedBlockHash *common.Hash) { @@ -1068,6 +1119,19 @@ func (s *TransactionStreamer) checkResult(msgResult *execution.MessageResult, ex } } +func (s *TransactionStreamer) storeResult( + pos arbutil.MessageIndex, + msgResult execution.MessageResult, + batch ethdb.Batch, +) error { + msgResultBytes, err := rlp.EncodeToBytes(msgResult) + if err != nil { + return err + } + key := dbKey(messageResultPrefix, uint64(pos)) + return batch.Put(key, msgResultBytes) +} + // exposed for testing // return value: true if should be called again immediately func (s *TransactionStreamer) ExecuteNextMsg(ctx context.Context, exec execution.ExecutionSequencer) bool { @@ -1120,6 +1184,18 @@ func (s *TransactionStreamer) ExecuteNextMsg(ctx context.Context, exec execution s.checkResult(msgResult, msgAndBlockHash.BlockHash) + batch := s.db.NewBatch() + err = s.storeResult(pos, *msgResult, batch) + if err != nil { + log.Error("feedOneMsg failed to store result", "err", err) + return false + } + err = batch.Write() + if err != nil { + log.Error("feedOneMsg failed to store result", "err", err) + return false + } + msgWithBlockHash := arbostypes.MessageWithMetadataAndBlockHash{ MessageWithMeta: msgAndBlockHash.MessageWithMeta, BlockHash: &msgResult.BlockHash, 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 486c6ae33a..c44febf386 100644 --- a/arbos/arbosState/initialize.go +++ b/arbos/arbosState/initialize.go @@ -9,6 +9,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" @@ -51,13 +52,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/block_processor.go b/arbos/block_processor.go index 9d6c420a57..b180405c43 100644 --- a/arbos/block_processor.go +++ b/arbos/block_processor.go @@ -22,7 +22,6 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" @@ -144,26 +143,9 @@ func ProduceBlock( statedb *state.StateDB, chainContext core.ChainContext, chainConfig *params.ChainConfig, - batchFetcher arbostypes.FallibleBatchFetcher, isMsgForPrefetch bool, ) (*types.Block, types.Receipts, error) { - var batchFetchErr error - txes, err := ParseL2Transactions(message, chainConfig.ChainID, func(batchNum uint64, batchHash common.Hash) []byte { - data, err := batchFetcher(batchNum) - if err != nil { - batchFetchErr = err - return nil - } - dataHash := crypto.Keccak256Hash(data) - if dataHash != batchHash { - batchFetchErr = fmt.Errorf("expecting batch %v hash %v but got data with hash %v", batchNum, batchHash, dataHash) - return nil - } - return data - }) - if batchFetchErr != nil { - return nil, nil, batchFetchErr - } + txes, err := ParseL2Transactions(message, chainConfig.ChainID) if err != nil { log.Warn("error parsing incoming message", "err", err) txes = types.Transactions{} diff --git a/arbos/incomingmessage_test.go b/arbos/incomingmessage_test.go index 14726a419f..2933f6a719 100644 --- a/arbos/incomingmessage_test.go +++ b/arbos/incomingmessage_test.go @@ -36,7 +36,7 @@ func TestSerializeAndParseL1Message(t *testing.T) { if err != nil { t.Error(err) } - txes, err := ParseL2Transactions(newMsg, chainId, nil) + txes, err := ParseL2Transactions(newMsg, chainId) if err != nil { t.Error(err) } diff --git a/arbos/parse_l2.go b/arbos/parse_l2.go index d2df3bdf89..06722e4063 100644 --- a/arbos/parse_l2.go +++ b/arbos/parse_l2.go @@ -17,9 +17,7 @@ import ( "github.com/offchainlabs/nitro/util/arbmath" ) -type InfallibleBatchFetcher func(batchNum uint64, batchHash common.Hash) []byte - -func ParseL2Transactions(msg *arbostypes.L1IncomingMessage, chainId *big.Int, batchFetcher InfallibleBatchFetcher) (types.Transactions, error) { +func ParseL2Transactions(msg *arbostypes.L1IncomingMessage, chainId *big.Int) (types.Transactions, error) { if len(msg.L2msg) > arbostypes.MaxL2MessageSize { // ignore the message if l2msg is too large return nil, errors.New("message too large") @@ -71,7 +69,7 @@ func ParseL2Transactions(msg *arbostypes.L1IncomingMessage, chainId *big.Int, ba log.Debug("ignoring rollup event message") return types.Transactions{}, nil case arbostypes.L1MessageType_BatchPostingReport: - tx, err := parseBatchPostingReportMessage(bytes.NewReader(msg.L2msg), chainId, msg.BatchGasCost, batchFetcher) + tx, err := parseBatchPostingReportMessage(bytes.NewReader(msg.L2msg), chainId, msg.BatchGasCost) if err != nil { return nil, err } @@ -370,8 +368,8 @@ func parseSubmitRetryableMessage(rd io.Reader, header *arbostypes.L1IncomingMess return types.NewTx(tx), err } -func parseBatchPostingReportMessage(rd io.Reader, chainId *big.Int, msgBatchGasCost *uint64, batchFetcher InfallibleBatchFetcher) (*types.Transaction, error) { - batchTimestamp, batchPosterAddr, batchHash, batchNum, l1BaseFee, extraGas, err := arbostypes.ParseBatchPostingReportMessageFields(rd) +func parseBatchPostingReportMessage(rd io.Reader, chainId *big.Int, msgBatchGasCost *uint64) (*types.Transaction, error) { + batchTimestamp, batchPosterAddr, _, batchNum, l1BaseFee, extraGas, err := arbostypes.ParseBatchPostingReportMessageFields(rd) if err != nil { return nil, err } @@ -379,8 +377,7 @@ func parseBatchPostingReportMessage(rd io.Reader, chainId *big.Int, msgBatchGasC if msgBatchGasCost != nil { batchDataGas = *msgBatchGasCost } else { - batchData := batchFetcher(batchNum, batchHash) - batchDataGas = arbostypes.ComputeBatchGasCost(batchData) + return nil, errors.New("cannot compute batch gas cost") } batchDataGas = arbmath.SaturatingUAdd(batchDataGas, extraGas) 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/arbstate/daprovider/util.go b/arbstate/daprovider/util.go index 8f880b9228..d5a369bf3c 100644 --- a/arbstate/daprovider/util.go +++ b/arbstate/daprovider/util.go @@ -11,6 +11,7 @@ import ( "errors" "fmt" "io" + "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -34,6 +35,8 @@ type DASWriter interface { fmt.Stringer } +var DefaultDASRetentionPeriod time.Duration = time.Hour * 24 * 15 + type DASKeysetFetcher interface { GetKeysetByHash(context.Context, common.Hash) ([]byte, error) } @@ -188,7 +191,7 @@ func RecoverPayloadFromDasBatch( keysetPreimage, err := keysetFetcher.GetKeysetByHash(ctx, cert.KeysetHash) if err != nil { - log.Error("Couldn't get keyset", "err", err) + log.Error("Couldn't get keyset", "err", err, "keysetHash", common.Bytes2Hex(cert.KeysetHash[:])) return nil, err } if preimageRecorder != nil { diff --git a/arbutil/wait_for_l1.go b/arbutil/wait_for_l1.go index eaa5d0790d..4b4819156d 100644 --- a/arbutil/wait_for_l1.go +++ b/arbutil/wait_for_l1.go @@ -19,12 +19,12 @@ import ( type L1Interface interface { bind.ContractBackend + bind.BlockHashContractCaller ethereum.ChainReader ethereum.ChainStateReader ethereum.TransactionReader TransactionSender(ctx context.Context, tx *types.Transaction, block common.Hash, index uint) (common.Address, error) BlockNumber(ctx context.Context) (uint64, error) - CallContractAtHash(ctx context.Context, msg ethereum.CallMsg, blockHash common.Hash) ([]byte, error) PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) ChainID(ctx context.Context) (*big.Int, error) Client() rpc.ClientInterface diff --git a/cmd/conf/init.go b/cmd/conf/init.go index 4bea00f9f2..a3b5504077 100644 --- a/cmd/conf/init.go +++ b/cmd/conf/init.go @@ -30,9 +30,11 @@ type InitConfig struct { PruneBloomSize uint64 `koanf:"prune-bloom-size"` PruneThreads int `koanf:"prune-threads"` PruneTrieCleanCache int `koanf:"prune-trie-clean-cache"` - ResetToMessage int64 `koanf:"reset-to-message"` RecreateMissingStateFrom uint64 `koanf:"recreate-missing-state-from"` RebuildLocalWasm bool `koanf:"rebuild-local-wasm"` + ReorgToBatch int64 `koanf:"reorg-to-batch"` + ReorgToMessageBatch int64 `koanf:"reorg-to-message-batch"` + ReorgToBlockBatch int64 `koanf:"reorg-to-block-batch"` } var InitConfigDefault = InitConfig{ @@ -54,9 +56,11 @@ var InitConfigDefault = InitConfig{ PruneBloomSize: 2048, PruneThreads: runtime.NumCPU(), PruneTrieCleanCache: gethexec.DefaultCachingConfig.TrieCleanCache, - ResetToMessage: -1, RecreateMissingStateFrom: 0, // 0 = disabled RebuildLocalWasm: true, + ReorgToBatch: -1, + ReorgToMessageBatch: -1, + ReorgToBlockBatch: -1, } func InitConfigAddOptions(prefix string, f *pflag.FlagSet) { @@ -78,9 +82,11 @@ func InitConfigAddOptions(prefix string, f *pflag.FlagSet) { f.Uint64(prefix+".prune-bloom-size", InitConfigDefault.PruneBloomSize, "the amount of memory in megabytes to use for the pruning bloom filter (higher values prune better)") f.Int(prefix+".prune-threads", InitConfigDefault.PruneThreads, "the number of threads to use when pruning") f.Int(prefix+".prune-trie-clean-cache", InitConfigDefault.PruneTrieCleanCache, "amount of memory in megabytes to cache unchanged state trie nodes with when traversing state database during pruning") - f.Int64(prefix+".reset-to-message", InitConfigDefault.ResetToMessage, "forces a reset to an old message height. Also set max-reorg-resequence-depth=0 to force re-reading messages") f.Uint64(prefix+".recreate-missing-state-from", InitConfigDefault.RecreateMissingStateFrom, "block number to start recreating missing states from (0 = disabled)") f.Bool(prefix+".rebuild-local-wasm", InitConfigDefault.RebuildLocalWasm, "rebuild local wasm database on boot if needed (otherwise-will be done lazily)") + f.Int64(prefix+".reorg-to-batch", InitConfigDefault.ReorgToBatch, "rolls back the blockchain to a specified batch number") + f.Int64(prefix+".reorg-to-message-batch", InitConfigDefault.ReorgToMessageBatch, "rolls back the blockchain to the first batch at or before a given message index") + f.Int64(prefix+".reorg-to-block-batch", InitConfigDefault.ReorgToBlockBatch, "rolls back the blockchain to the first batch at or before a given block number") } func (c *InitConfig) Validate() error { @@ -96,9 +102,22 @@ func (c *InitConfig) Validate() error { if c.PruneTrieCleanCache < 0 { return fmt.Errorf("invalid trie clean cache size: %d, has to be greater or equal 0", c.PruneTrieCleanCache) } + numReorgOptionsSpecified := 0 + for _, reorgOption := range []int64{c.ReorgToBatch, c.ReorgToMessageBatch, c.ReorgToBlockBatch} { + if reorgOption >= 0 { + numReorgOptionsSpecified++ + if numReorgOptionsSpecified > 1 { + return fmt.Errorf("at most one init reorg option can be specified") + } + } + } return nil } +func (c *InitConfig) IsReorgRequested() bool { + return c.ReorgToBatch >= 0 || c.ReorgToBlockBatch >= 0 || c.ReorgToMessageBatch >= 0 +} + var ( acceptedSnapshotKinds = []string{"archive", "pruned", "genesis"} acceptedSnapshotKindsStr = "(accepted values: \"" + strings.Join(acceptedSnapshotKinds, "\" | \"") + "\")" 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..2c7d07cf3b 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" @@ -40,6 +41,7 @@ import ( "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics/exp" "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/params" "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbnode/resourcemanager" @@ -512,7 +514,7 @@ func mainImpl() int { } } - if nodeConfig.Init.ThenQuit && nodeConfig.Init.ResetToMessage < 0 { + if nodeConfig.Init.ThenQuit && !nodeConfig.Init.IsReorgRequested() { return 0 } @@ -668,29 +670,34 @@ func mainImpl() int { sigint := make(chan os.Signal, 1) signal.Notify(sigint, os.Interrupt, syscall.SIGTERM) - exitCode := 0 - - if err == nil && nodeConfig.Init.ResetToMessage > 0 { - err = currentNode.TxStreamer.ReorgTo(arbutil.MessageIndex(nodeConfig.Init.ResetToMessage)) + if err == nil && nodeConfig.Init.IsReorgRequested() { + err = initReorg(nodeConfig.Init, chainInfo.ChainConfig, currentNode.InboxTracker) if err != nil { - fatalErrChan <- fmt.Errorf("error reseting message: %w", err) - exitCode = 1 - } - if nodeConfig.Init.ThenQuit { - return exitCode + fatalErrChan <- fmt.Errorf("error reorging per init config: %w", err) + } else if nodeConfig.Init.ThenQuit { + return 0 } } + err = nil select { - case err := <-fatalErrChan: + case err = <-fatalErrChan: + case <-sigint: + // If there was both a sigint and a fatal error, we want to log the fatal error + select { + case err = <-fatalErrChan: + default: + log.Info("shutting down because of sigint") + } + } + + if err != nil { log.Error("shutting down due to fatal error", "err", err) defer log.Error("shut down due to fatal error", "err", err) - exitCode = 1 - case <-sigint: - log.Info("shutting down because of sigint") + return 1 } - return exitCode + return 0 } type NodeConfig struct { @@ -836,6 +843,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() } @@ -999,6 +1009,39 @@ func applyChainParameters(ctx context.Context, k *koanf.Koanf, chainId uint64, c return nil } +func initReorg(initConfig conf.InitConfig, chainConfig *params.ChainConfig, inboxTracker *arbnode.InboxTracker) error { + var batchCount uint64 + if initConfig.ReorgToBatch >= 0 { + batchCount = uint64(initConfig.ReorgToBatch) + 1 + } else { + var messageIndex arbutil.MessageIndex + if initConfig.ReorgToMessageBatch >= 0 { + messageIndex = arbutil.MessageIndex(initConfig.ReorgToMessageBatch) + } else if initConfig.ReorgToBlockBatch > 0 { + genesis := chainConfig.ArbitrumChainParams.GenesisBlockNum + blockNum := uint64(initConfig.ReorgToBlockBatch) + if blockNum < genesis { + return fmt.Errorf("ReorgToBlockBatch %d before genesis %d", blockNum, genesis) + } + messageIndex = arbutil.MessageIndex(blockNum - genesis) + } else { + log.Warn("Tried to do init reorg, but no init reorg options specified") + return nil + } + // Reorg out the batch containing the next message + var missing bool + var err error + batchCount, missing, err = inboxTracker.FindInboxBatchContainingMessage(messageIndex + 1) + if err != nil { + return err + } + if missing { + return fmt.Errorf("cannot reorg to unknown message index %v", messageIndex) + } + } + return inboxTracker.ReorgBatchesTo(batchCount) +} + type NodeConfigFetcher struct { *genericconf.LiveConfig[*NodeConfig] } 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/replay/main.go b/cmd/replay/main.go index 5723b4a030..0fe56eb4c9 100644 --- a/cmd/replay/main.go +++ b/cmd/replay/main.go @@ -203,6 +203,13 @@ func main() { panic(fmt.Sprintf("Error opening state db: %v", err.Error())) } + batchFetcher := func(batchNum uint64) ([]byte, error) { + currentBatch := wavmio.GetInboxPosition() + if batchNum > currentBatch { + return nil, fmt.Errorf("invalid batch fetch request %d, max %d", batchNum, currentBatch) + } + return wavmio.ReadInboxMessage(batchNum), nil + } readMessage := func(dasEnabled bool) *arbostypes.MessageWithMetadata { var delayedMessagesRead uint64 if lastBlockHeader != nil { @@ -232,6 +239,10 @@ func main() { panic(fmt.Sprintf("Error reading from inbox multiplexer: %v", err.Error())) } + err = message.Message.FillInBatchGasCost(batchFetcher) + if err != nil { + message.Message = arbostypes.InvalidL1Message + } return message } @@ -280,14 +291,10 @@ func main() { message := readMessage(chainConfig.ArbitrumChainParams.DataAvailabilityCommittee) chainContext := WavmChainContext{} - batchFetcher := func(batchNum uint64) ([]byte, error) { - return wavmio.ReadInboxMessage(batchNum), nil - } - newBlock, _, err = arbos.ProduceBlock(message.Message, message.DelayedMessagesRead, lastBlockHeader, statedb, chainContext, chainConfig, batchFetcher, false) + newBlock, _, err = arbos.ProduceBlock(message.Message, message.DelayedMessagesRead, lastBlockHeader, statedb, chainContext, chainConfig, false) if err != nil { panic(err) } - } else { // Initialize ArbOS with this init message and create the genesis block. diff --git a/cmd/staterecovery/staterecovery.go b/cmd/staterecovery/staterecovery.go index 58ad06ad14..bb01477414 100644 --- a/cmd/staterecovery/staterecovery.go +++ b/cmd/staterecovery/staterecovery.go @@ -5,12 +5,13 @@ 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" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/trie" - "github.com/ethereum/go-ethereum/trie/triedb/hashdb" + "github.com/ethereum/go-ethereum/triedb" + "github.com/ethereum/go-ethereum/triedb/hashdb" ) func RecreateMissingStates(chainDb ethdb.Database, bc *core.BlockChain, cacheConfig *core.CacheConfig, startBlock uint64) error { @@ -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 := &trie.Config{ + 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/contracts b/contracts index 61204dd455..f7894d3a6d 160000 --- a/contracts +++ b/contracts @@ -1 +1 @@ -Subproject commit 61204dd455966cb678192427a07aa9795ff91c14 +Subproject commit f7894d3a6d4035ba60f51a7f1334f0f2d4f02dce diff --git a/das/aggregator.go b/das/aggregator.go index 9aa558b92c..d944f8d48a 100644 --- a/das/aggregator.go +++ b/das/aggregator.go @@ -193,11 +193,7 @@ func (a *Aggregator) Store(ctx context.Context, message []byte, timeout uint64) cert, err := d.service.Store(storeCtx, message, timeout) if err != nil { incFailureMetric() - if errors.Is(err, context.DeadlineExceeded) { - metrics.GetOrRegisterCounter(metricWithServiceName+"/error/timeout/total", nil).Inc(1) - } else { - metrics.GetOrRegisterCounter(metricWithServiceName+"/error/client/total", nil).Inc(1) - } + log.Warn("DAS Aggregator failed to store batch to backend", "backend", d.metricName, "err", err) responses <- storeResponse{d, nil, err} return } @@ -207,13 +203,13 @@ func (a *Aggregator) Store(ctx context.Context, message []byte, timeout uint64) ) if err != nil { incFailureMetric() - metrics.GetOrRegisterCounter(metricWithServiceName+"/error/bad_response/total", nil).Inc(1) + log.Warn("DAS Aggregator couldn't parse backend's store response signature", "backend", d.metricName, "err", err) responses <- storeResponse{d, nil, err} return } if !verified { incFailureMetric() - metrics.GetOrRegisterCounter(metricWithServiceName+"/error/bad_response/total", nil).Inc(1) + log.Warn("DAS Aggregator failed to verify backend's store response signature", "backend", d.metricName, "err", err) responses <- storeResponse{d, nil, errors.New("signature verification failed")} return } @@ -222,13 +218,13 @@ func (a *Aggregator) Store(ctx context.Context, message []byte, timeout uint64) if cert.DataHash != expectedHash { incFailureMetric() - metrics.GetOrRegisterCounter(metricWithServiceName+"/error/bad_response/total", nil).Inc(1) + log.Warn("DAS Aggregator got a store response with a data hash not matching the expected hash", "backend", d.metricName, "dataHash", cert.DataHash, "expectedHash", expectedHash, "err", err) responses <- storeResponse{d, nil, errors.New("hash verification failed")} return } if cert.Timeout != timeout { incFailureMetric() - metrics.GetOrRegisterCounter(metricWithServiceName+"/error/bad_response/total", nil).Inc(1) + log.Warn("DAS Aggregator got a store response with any expiry time not matching the expected expiry time", "backend", d.metricName, "dataHash", cert.DataHash, "expectedHash", expectedHash, "err", err) responses <- storeResponse{d, nil, fmt.Errorf("timeout was %d, expected %d", cert.Timeout, timeout)} return } diff --git a/das/local_file_storage_service.go b/das/local_file_storage_service.go index 621cf3efdb..65ca6fe15c 100644 --- a/das/local_file_storage_service.go +++ b/das/local_file_storage_service.go @@ -110,17 +110,21 @@ func (s *LocalFileStorageService) Close(ctx context.Context) error { func (s *LocalFileStorageService) GetByHash(ctx context.Context, key common.Hash) ([]byte, error) { log.Trace("das.LocalFileStorageService.GetByHash", "key", pretty.PrettyHash(key), "this", s) - var batchPath string - if s.enableLegacyLayout { - batchPath = s.legacyLayout.batchPath(key) - } else { - batchPath = s.layout.batchPath(key) - } + + legacyBatchPath := s.legacyLayout.batchPath(key) + batchPath := s.layout.batchPath(key) data, err := os.ReadFile(batchPath) if err != nil { if errors.Is(err, os.ErrNotExist) { - return nil, ErrNotFound + data, err = os.ReadFile(legacyBatchPath) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + return nil, ErrNotFound + } + return nil, err + } + return data, nil } return nil, err } @@ -224,8 +228,15 @@ func (s *LocalFileStorageService) String() string { } func (s *LocalFileStorageService) HealthCheck(ctx context.Context) error { - testData := []byte("Test-Data") - err := s.Put(ctx, testData, uint64(time.Now().Add(time.Minute).Unix())) + testData := []byte("Test Data") + // Store some data with an expiry time at the start of the epoch. + // If expiry is disabled it will only create an index entry for the + // same timestamp each time the health check happens. + // If expiry is enabled, it will be cleaned up each time the pruning + // runs. There is a slight chance of a race between pruning and the + // Put and Get calls, but systems using the HealthCheck will just retry + // and succeed the next time. + err := s.Put(ctx, testData, 0 /* start of epoch */) if err != nil { return err } @@ -726,6 +737,8 @@ func (l *trieLayout) commitMigration() error { return err } + // in OSX - syscall.Sync() returns an error, but in linux it does not. + // nolint:errcheck syscall.Sync() // Done migrating diff --git a/das/syncing_fallback_storage.go b/das/syncing_fallback_storage.go index 1cf6a832f3..ee0ddc6b5f 100644 --- a/das/syncing_fallback_storage.go +++ b/das/syncing_fallback_storage.go @@ -68,7 +68,7 @@ type SyncToStorageConfig struct { var DefaultSyncToStorageConfig = SyncToStorageConfig{ Eager: false, EagerLowerBoundBlock: 0, - RetentionPeriod: defaultStorageRetention, + RetentionPeriod: daprovider.DefaultDASRetentionPeriod, DelayOnError: time.Second, IgnoreWriteErrors: true, ParentChainBlocksPerRead: 100, diff --git a/execution/gethexec/block_recorder.go b/execution/gethexec/block_recorder.go index 5b509b97fc..8879c90702 100644 --- a/execution/gethexec/block_recorder.go +++ b/execution/gethexec/block_recorder.go @@ -16,7 +16,6 @@ import ( "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/execution" - "github.com/offchainlabs/nitro/validator" ) // BlockRecorder uses a separate statedatabase from the blockchain. @@ -120,23 +119,7 @@ func (r *BlockRecorder) RecordBlockCreation( } var blockHash common.Hash - var readBatchInfo []validator.BatchInfo if msg != nil { - batchFetcher := func(batchNum uint64) ([]byte, error) { - data, blockHash, err := r.execEngine.consensus.FetchBatch(ctx, batchNum) - if err != nil { - return nil, err - } - readBatchInfo = append(readBatchInfo, validator.BatchInfo{ - Number: batchNum, - BlockHash: blockHash, - Data: data, - }) - return data, nil - } - // Re-fetch the batch instead of using our cached cost, - // as the replay binary won't have the cache populated. - msg.Message.BatchGasCost = nil block, _, err := arbos.ProduceBlock( msg.Message, msg.DelayedMessagesRead, @@ -144,7 +127,6 @@ func (r *BlockRecorder) RecordBlockCreation( recordingdb, chaincontext, chainConfig, - batchFetcher, false, ) if err != nil { @@ -172,7 +154,6 @@ func (r *BlockRecorder) RecordBlockCreation( Pos: pos, BlockHash: blockHash, Preimages: preimages, - BatchInfo: readBatchInfo, UserWasms: recordingdb.UserWasms(), }, err } 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/executionengine.go b/execution/gethexec/executionengine.go index 95b865df5a..d8a592736c 100644 --- a/execution/gethexec/executionengine.go +++ b/execution/gethexec/executionengine.go @@ -355,8 +355,7 @@ func (s *ExecutionEngine) resequenceReorgedMessages(messages []*arbostypes.Messa log.Warn("skipping non-standard sequencer message found from reorg", "header", header) continue } - // We don't need a batch fetcher as this is an L2 message - txes, err := arbos.ParseL2Transactions(msg.Message, s.bc.Config().ChainID, nil) + txes, err := arbos.ParseL2Transactions(msg.Message, s.bc.Config().ChainID) if err != nil { log.Warn("failed to parse sequencer message found from reorg", "err", err) continue @@ -625,11 +624,6 @@ func (s *ExecutionEngine) createBlockFromNextMessage(msg *arbostypes.MessageWith statedb.StartPrefetcher("TransactionStreamer") defer statedb.StopPrefetcher() - batchFetcher := func(num uint64) ([]byte, error) { - data, _, err := s.consensus.FetchBatch(s.GetContext(), num) - return data, err - } - block, receipts, err := arbos.ProduceBlock( msg.Message, msg.DelayedMessagesRead, @@ -637,7 +631,6 @@ func (s *ExecutionEngine) createBlockFromNextMessage(msg *arbostypes.MessageWith statedb, s.bc, s.bc.Config(), - batchFetcher, isMsgForPrefetch, ) 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..6624188cbd 100644 --- a/execution/gethexec/node.go +++ b/execution/gethexec/node.go @@ -26,18 +26,6 @@ import ( flag "github.com/spf13/pflag" ) -type DangerousConfig struct { - ReorgToBlock int64 `koanf:"reorg-to-block"` -} - -var DefaultDangerousConfig = DangerousConfig{ - ReorgToBlock: -1, -} - -func DangerousConfigAddOptions(prefix string, f *flag.FlagSet) { - f.Int64(prefix+".reorg-to-block", DefaultDangerousConfig.ReorgToBlock, "DANGEROUS! forces a reorg to an old block height. To be used for testing only. -1 to disable") -} - type Config struct { ParentChainReader headerreader.Config `koanf:"parent-chain-reader" reload:"hot"` Sequencer SequencerConfig `koanf:"sequencer" reload:"hot"` @@ -49,7 +37,6 @@ type Config struct { Caching CachingConfig `koanf:"caching"` RPC arbitrum.Config `koanf:"rpc"` TxLookupLimit uint64 `koanf:"tx-lookup-limit"` - Dangerous DangerousConfig `koanf:"dangerous"` EnablePrefetchBlock bool `koanf:"enable-prefetch-block"` SyncMonitor SyncMonitorConfig `koanf:"sync-monitor"` @@ -57,6 +44,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 } @@ -86,7 +76,6 @@ func ConfigAddOptions(prefix string, f *flag.FlagSet) { CachingConfigAddOptions(prefix+".caching", f) SyncMonitorConfigAddOptions(prefix+".sync-monitor", f) f.Uint64(prefix+".tx-lookup-limit", ConfigDefault.TxLookupLimit, "retain the ability to lookup transactions by hash for the past N blocks (0 = all blocks)") - DangerousConfigAddOptions(prefix+".dangerous", f) f.Bool(prefix+".enable-prefetch-block", ConfigDefault.EnablePrefetchBlock, "enable prefetching of blocks") } @@ -100,36 +89,10 @@ var ConfigDefault = Config{ TxPreChecker: DefaultTxPreCheckerConfig, TxLookupLimit: 126_230_400, // 1 year at 4 blocks per second Caching: DefaultCachingConfig, - Dangerous: DefaultDangerousConfig, Forwarder: DefaultNodeForwarderConfig, 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 1bd7268031..90e3082062 100644 --- a/execution/gethexec/sequencer.go +++ b/execution/gethexec/sequencer.go @@ -131,24 +131,6 @@ var DefaultSequencerConfig = SequencerConfig{ EnableProfiling: false, } -var TestSequencerConfig = SequencerConfig{ - Enable: true, - MaxBlockSpeed: time.Millisecond * 10, - MaxRevertGasReject: params.TxGas + 10000, - MaxAcceptableTimestampDelta: time.Hour, - SenderWhitelist: []string{}, - 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/execution/interface.go b/execution/interface.go index ddf30b4b2a..2a3d79c697 100644 --- a/execution/interface.go +++ b/execution/interface.go @@ -9,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbutil" - "github.com/offchainlabs/nitro/validator" ) type MessageResult struct { @@ -21,7 +20,6 @@ type RecordResult struct { Pos arbutil.MessageIndex BlockHash common.Hash Preimages map[common.Hash][]byte - BatchInfo []validator.BatchInfo UserWasms state.UserWasms } @@ -77,7 +75,6 @@ type FullExecutionClient interface { // not implemented in execution, used as input // BatchFetcher is required for any execution node type BatchFetcher interface { - FetchBatch(ctx context.Context, batchNum uint64) ([]byte, common.Hash, error) FindInboxBatchContainingMessage(message arbutil.MessageIndex) (uint64, bool, error) GetBatchParentChainBlock(seqNum uint64) (uint64, error) } diff --git a/gethhook/geth_test.go b/gethhook/geth_test.go index 99bfa4ae1c..57ce2ddec0 100644 --- a/gethhook/geth_test.go +++ b/gethhook/geth_test.go @@ -123,7 +123,7 @@ func RunMessagesThroughAPI(t *testing.T, msgs [][]byte, statedb *state.StateDB) if err != nil { t.Error(err) } - txes, err := arbos.ParseL2Transactions(msg, chainId, nil) + txes, err := arbos.ParseL2Transactions(msg, chainId) if err != nil { t.Error(err) } diff --git a/go-ethereum b/go-ethereum index c186780e82..48de2030c7 160000 --- a/go-ethereum +++ b/go-ethereum @@ -1 +1 @@ -Subproject commit c186780e82856be27d1576db4d1fd79984562165 +Subproject commit 48de2030c7a6fa8689bc0a0212ebca2a0c73e3ad diff --git a/go.mod b/go.mod index 00cee1a99a..123d7ea59a 100644 --- a/go.mod +++ b/go.mod @@ -50,7 +50,10 @@ require ( gopkg.in/natefinch/lumberjack.v2 v2.0.0 ) -require github.com/google/go-querystring v1.1.0 // indirect +require ( + github.com/google/btree v1.1.2 // indirect + github.com/google/go-querystring v1.1.0 // indirect +) require ( github.com/DataDog/zstd v1.4.5 // indirect @@ -118,7 +121,7 @@ require ( github.com/graph-gophers/graphql-go v1.3.0 // indirect github.com/h2non/filetype v1.0.6 // indirect github.com/hashicorp/go-bexpr v0.1.10 // indirect - github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 // indirect + github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 // indirect github.com/holiman/bloomfilter/v2 v2.0.3 // indirect github.com/huin/goupnp v1.3.0 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect @@ -161,10 +164,10 @@ require ( github.com/yuin/gopher-lua v1.1.1 // indirect go.opencensus.io v0.22.5 // indirect golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.21.0 // indirect - golang.org/x/sync v0.5.0 // indirect + golang.org/x/net v0.23.0 // indirect + golang.org/x/sync v0.5.0 golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 8676c270c4..f0580a6c1d 100644 --- a/go.sum +++ b/go.sum @@ -340,7 +340,10 @@ github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXi github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= +github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -420,8 +423,8 @@ github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoI github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7 h1:3JQNjnMRil1yD0IfZKHF9GxxWKDJGj8I0IqOUol//sw= -github.com/holiman/billy v0.0.0-20230718173358-1c7e68d277a7/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6wn4Ej8vjuVGxeHdan+bRb2ebyv4= +github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= @@ -827,8 +830,8 @@ golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1089,8 +1092,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/nitro-testnode b/nitro-testnode index 9dc0588c50..f328006579 160000 --- a/nitro-testnode +++ b/nitro-testnode @@ -1 +1 @@ -Subproject commit 9dc0588c5066e2efd25c09adf12df7b28ef18cb6 +Subproject commit f328006579cbefe22c6c57de3d6b86397fde4438 diff --git a/pubsub/common.go b/pubsub/common.go index 9f05304e46..d7f041af15 100644 --- a/pubsub/common.go +++ b/pubsub/common.go @@ -2,6 +2,7 @@ package pubsub import ( "context" + "strings" "github.com/ethereum/go-ethereum/log" "github.com/go-redis/redis/v8" @@ -22,7 +23,9 @@ func CreateStream(ctx context.Context, streamName string, client redis.Universal func StreamExists(ctx context.Context, streamName string, client redis.UniversalClient) bool { got, err := client.Do(ctx, "XINFO", "STREAM", streamName).Result() if err != nil { - log.Error("Reading redis streams", "error", err) + if !strings.Contains(err.Error(), "no such key") { + log.Error("redis error", "err", err, "searching stream", streamName) + } return false } return got != nil diff --git a/pubsub/producer.go b/pubsub/producer.go index 074670ca0f..2b1cdb5e3f 100644 --- a/pubsub/producer.go +++ b/pubsub/producer.go @@ -13,6 +13,9 @@ import ( "encoding/json" "errors" "fmt" + "math" + "strconv" + "strings" "sync" "time" @@ -59,6 +62,7 @@ type ProducerConfig struct { KeepAliveTimeout time.Duration `koanf:"keepalive-timeout"` // Interval duration for checking the result set by consumers. CheckResultInterval time.Duration `koanf:"check-result-interval"` + CheckPendingItems int64 `koanf:"check-pending-items"` } var DefaultProducerConfig = ProducerConfig{ @@ -66,13 +70,15 @@ var DefaultProducerConfig = ProducerConfig{ CheckPendingInterval: time.Second, KeepAliveTimeout: 5 * time.Minute, CheckResultInterval: 5 * time.Second, + CheckPendingItems: 256, } var TestProducerConfig = ProducerConfig{ - EnableReproduce: true, + EnableReproduce: false, CheckPendingInterval: 10 * time.Millisecond, KeepAliveTimeout: 100 * time.Millisecond, CheckResultInterval: 5 * time.Millisecond, + CheckPendingItems: 256, } func ProducerAddConfigAddOptions(prefix string, f *pflag.FlagSet) { @@ -80,6 +86,7 @@ func ProducerAddConfigAddOptions(prefix string, f *pflag.FlagSet) { f.Duration(prefix+".check-pending-interval", DefaultProducerConfig.CheckPendingInterval, "interval in which producer checks pending messages whether consumer processing them is inactive") f.Duration(prefix+".check-result-interval", DefaultProducerConfig.CheckResultInterval, "interval in which producer checks pending messages whether consumer processing them is inactive") f.Duration(prefix+".keepalive-timeout", DefaultProducerConfig.KeepAliveTimeout, "timeout after which consumer is considered inactive if heartbeat wasn't performed") + f.Int64(prefix+".check-pending-items", DefaultProducerConfig.CheckPendingItems, "items to screen during check-pending") } func NewProducer[Request any, Response any](client redis.UniversalClient, streamName string, cfg *ProducerConfig) (*Producer[Request, Response], error) { @@ -99,13 +106,13 @@ func NewProducer[Request any, Response any](client redis.UniversalClient, stream }, nil } -func (p *Producer[Request, Response]) errorPromisesFor(msgs []*Message[Request]) { +func (p *Producer[Request, Response]) errorPromisesFor(msgIds []string) { p.promisesLock.Lock() defer p.promisesLock.Unlock() - for _, msg := range msgs { - if promise, found := p.promises[msg.ID]; found { + for _, msg := range msgIds { + if promise, found := p.promises[msg]; found { promise.ProduceError(fmt.Errorf("internal error, consumer died while serving the request")) - delete(p.promises, msg.ID) + delete(p.promises, msg) } } } @@ -113,56 +120,132 @@ func (p *Producer[Request, Response]) errorPromisesFor(msgs []*Message[Request]) // checkAndReproduce reproduce pending messages that were sent to consumers // that are currently inactive. func (p *Producer[Request, Response]) checkAndReproduce(ctx context.Context) time.Duration { - msgs, err := p.checkPending(ctx) + staleIds, err := p.checkPending(ctx) if err != nil { log.Error("Checking pending messages", "error", err) return p.cfg.CheckPendingInterval } - if len(msgs) == 0 { + if len(staleIds) == 0 { return p.cfg.CheckPendingInterval } - if !p.cfg.EnableReproduce { - p.errorPromisesFor(msgs) - return p.cfg.CheckPendingInterval + if p.cfg.EnableReproduce { + err = p.reproduceIds(ctx, staleIds) + if err != nil { + log.Warn("filed reproducing messages", "err", err) + } + } else { + p.errorPromisesFor(staleIds) } - acked := make(map[string]Request) - for _, msg := range msgs { + return p.cfg.CheckPendingInterval +} + +func (p *Producer[Request, Response]) reproduceIds(ctx context.Context, staleIds []string) error { + log.Info("Attempting to claim", "messages", staleIds) + claimedMsgs, err := p.client.XClaim(ctx, &redis.XClaimArgs{ + Stream: p.redisStream, + Group: p.redisGroup, + Consumer: p.id, + MinIdle: p.cfg.KeepAliveTimeout, + Messages: staleIds, + }).Result() + if err != nil { + return fmt.Errorf("claiming ownership on messages: %v, error: %w", staleIds, err) + } + for _, msg := range claimedMsgs { + data, ok := (msg.Values[messageKey]).(string) + if !ok { + log.Error("redis producer reproduce: message not string", "id", msg.ID, "value", msg.Values[messageKey]) + continue + } + var req Request + if err := json.Unmarshal([]byte(data), &req); err != nil { + log.Error("redis producer reproduce: message not a request", "id", msg.ID, "err", err, "value", msg.Values[messageKey]) + continue + } if _, err := p.client.XAck(ctx, p.redisStream, p.redisGroup, msg.ID).Result(); err != nil { - log.Error("ACKing message", "error", err) + log.Error("redis producer reproduce: could not ACK", "id", msg.ID, "err", err) continue } - acked[msg.ID] = msg.Value - } - for k, v := range acked { // Only re-insert messages that were removed the the pending list first. - _, err := p.reproduce(ctx, v, k) - if err != nil { - log.Error("Re-inserting pending messages with inactive consumers", "error", err) + if _, err := p.reproduce(ctx, req, msg.ID); err != nil { + log.Error("redis producer reproduce: error", "err", err) } } - return p.cfg.CheckPendingInterval + return nil +} + +func setMinIdInt(min *[2]uint64, id string) error { + idParts := strings.Split(id, "-") + if len(idParts) != 2 { + return fmt.Errorf("invalid i.d: %v", id) + } + idTimeStamp, err := strconv.ParseUint(idParts[0], 10, 64) + if err != nil { + return fmt.Errorf("invalid i.d: %v err: %w", id, err) + } + if idTimeStamp > min[0] { + return nil + } + idSerial, err := strconv.ParseUint(idParts[1], 10, 64) + if err != nil { + return fmt.Errorf("invalid i.d serial: %v err: %w", id, err) + } + if idTimeStamp < min[0] { + min[0] = idTimeStamp + min[1] = idSerial + return nil + } + // idTimeStamp == min[0] + if idSerial < min[1] { + min[1] = idSerial + } + return nil } // checkResponses checks iteratively whether response for the promise is ready. func (p *Producer[Request, Response]) checkResponses(ctx context.Context) time.Duration { + minIdInt := [2]uint64{math.MaxUint64, math.MaxUint64} p.promisesLock.Lock() defer p.promisesLock.Unlock() + responded := 0 + errored := 0 for id, promise := range p.promises { + if ctx.Err() != nil { + return 0 + } res, err := p.client.Get(ctx, id).Result() if err != nil { - if errors.Is(err, redis.Nil) { - continue + errSetId := setMinIdInt(&minIdInt, id) + if errSetId != nil { + log.Error("error setting minId", "err", err) + return p.cfg.CheckResultInterval + } + if !errors.Is(err, redis.Nil) { + log.Error("Error reading value in redis", "key", id, "error", err) } - log.Error("Error reading value in redis", "key", id, "error", err) + continue } var resp Response if err := json.Unmarshal([]byte(res), &resp); err != nil { + promise.ProduceError(fmt.Errorf("error unmarshalling: %w", err)) log.Error("Error unmarshaling", "value", res, "error", err) - continue + errored++ + } else { + promise.Produce(resp) + responded++ } - promise.Produce(resp) delete(p.promises, id) } + var trimmed int64 + var trimErr error + minId := "+" + if minIdInt[0] < math.MaxUint64 { + minId = fmt.Sprintf("%d-%d", minIdInt[0], minIdInt[1]) + trimmed, trimErr = p.client.XTrimMinID(ctx, p.redisStream, minId).Result() + } else { + trimmed, trimErr = p.client.XTrimMaxLen(ctx, p.redisStream, 0).Result() + } + log.Trace("trimming", "id", minId, "trimmed", trimmed, "responded", responded, "errored", errored, "trim-err", trimErr) return p.cfg.CheckResultInterval } @@ -184,6 +267,10 @@ func (p *Producer[Request, Response]) reproduce(ctx context.Context, value Reque if err != nil { return nil, fmt.Errorf("marshaling value: %w", err) } + // catching the promiseLock before we sendXadd makes sure promise ids will + // be always ascending + p.promisesLock.Lock() + defer p.promisesLock.Unlock() id, err := p.client.XAdd(ctx, &redis.XAddArgs{ Stream: p.redisStream, Values: map[string]any{messageKey: val}, @@ -191,13 +278,12 @@ func (p *Producer[Request, Response]) reproduce(ctx context.Context, value Reque if err != nil { return nil, fmt.Errorf("adding values to redis: %w", err) } - p.promisesLock.Lock() - defer p.promisesLock.Unlock() promise := p.promises[oldKey] if oldKey != "" && promise == nil { // This will happen if the old consumer became inactive but then ack_d // the message afterwards. - return nil, fmt.Errorf("error reproducing the message, could not find existing one") + // don't error + log.Warn("tried reproducing a message but it wasn't found - probably got response", "oldKey", oldKey) } if oldKey == "" || promise == nil { pr := containers.NewPromise[Response](nil) @@ -232,13 +318,14 @@ func (p *Producer[Request, Response]) havePromiseFor(messageID string) bool { return found } -func (p *Producer[Request, Response]) checkPending(ctx context.Context) ([]*Message[Request], error) { +// returns ids of pending messages that's worker doesn't appear alive +func (p *Producer[Request, Response]) checkPending(ctx context.Context) ([]string, error) { pendingMessages, err := p.client.XPendingExt(ctx, &redis.XPendingExtArgs{ Stream: p.redisStream, Group: p.redisGroup, Start: "-", End: "+", - Count: 100, + Count: p.cfg.CheckPendingItems, }).Result() if err != nil && !errors.Is(err, redis.Nil) { @@ -247,6 +334,9 @@ func (p *Producer[Request, Response]) checkPending(ctx context.Context) ([]*Mess if len(pendingMessages) == 0 { return nil, nil } + if len(pendingMessages) >= int(p.cfg.CheckPendingItems) { + log.Warn("redis producer: many pending items found", "stream", p.redisStream, "check-pending-items", p.cfg.CheckPendingItems) + } // IDs of the pending messages with inactive consumers. var ids []string active := make(map[string]bool) @@ -265,35 +355,5 @@ func (p *Producer[Request, Response]) checkPending(ctx context.Context) ([]*Mess } ids = append(ids, msg.ID) } - if len(ids) == 0 { - log.Trace("There are no pending messages with inactive consumers") - return nil, nil - } - log.Info("Attempting to claim", "messages", ids) - claimedMsgs, err := p.client.XClaim(ctx, &redis.XClaimArgs{ - Stream: p.redisStream, - Group: p.redisGroup, - Consumer: p.id, - MinIdle: p.cfg.KeepAliveTimeout, - Messages: ids, - }).Result() - if err != nil { - return nil, fmt.Errorf("claiming ownership on messages: %v, error: %w", ids, err) - } - var res []*Message[Request] - for _, msg := range claimedMsgs { - data, ok := (msg.Values[messageKey]).(string) - if !ok { - return nil, fmt.Errorf("casting request: %v to bytes", msg.Values[messageKey]) - } - var req Request - if err := json.Unmarshal([]byte(data), &req); err != nil { - return nil, fmt.Errorf("marshaling value: %v, error: %w", msg.Values[messageKey], err) - } - res = append(res, &Message[Request]{ - ID: msg.ID, - Value: req, - }) - } - return res, nil + return ids, nil } diff --git a/pubsub/pubsub_test.go b/pubsub/pubsub_test.go index 72504602e3..9f774b6372 100644 --- a/pubsub/pubsub_test.go +++ b/pubsub/pubsub_test.go @@ -49,10 +49,12 @@ type configOpt interface { apply(consCfg *ConsumerConfig, prodCfg *ProducerConfig) } -type disableReproduce struct{} +type withReproduce struct { + reproduce bool +} -func (e *disableReproduce) apply(_ *ConsumerConfig, prodCfg *ProducerConfig) { - prodCfg.EnableReproduce = false +func (e *withReproduce) apply(_ *ConsumerConfig, prodCfg *ProducerConfig) { + prodCfg.EnableReproduce = e.reproduce } func producerCfg() *ProducerConfig { @@ -61,6 +63,7 @@ func producerCfg() *ProducerConfig { CheckPendingInterval: TestProducerConfig.CheckPendingInterval, KeepAliveTimeout: TestProducerConfig.KeepAliveTimeout, CheckResultInterval: TestProducerConfig.CheckResultInterval, + CheckPendingItems: TestProducerConfig.CheckPendingItems, } } @@ -71,7 +74,7 @@ func consumerCfg() *ConsumerConfig { } } -func newProducerConsumers(ctx context.Context, t *testing.T, opts ...configOpt) (*Producer[testRequest, testResponse], []*Consumer[testRequest, testResponse]) { +func newProducerConsumers(ctx context.Context, t *testing.T, opts ...configOpt) (redis.UniversalClient, string, *Producer[testRequest, testResponse], []*Consumer[testRequest, testResponse]) { t.Helper() redisClient, err := redisutil.RedisClientFromURL(redisutil.CreateTestRedis(ctx, t)) if err != nil { @@ -107,7 +110,7 @@ func newProducerConsumers(ctx context.Context, t *testing.T, opts ...configOpt) log.Debug("Error deleting heartbeat keys", "error", err) } }) - return producer, consumers + return redisClient, streamName, producer, consumers } func messagesMaps(n int) []map[string]string { @@ -118,10 +121,14 @@ func messagesMaps(n int) []map[string]string { return ret } +func msgForIndex(idx int) string { + return fmt.Sprintf("msg: %d", idx) +} + func wantMessages(n int) []string { var ret []string for i := 0; i < n; i++ { - ret = append(ret, fmt.Sprintf("msg: %d", i)) + ret = append(ret, msgForIndex(i)) } sort.Strings(ret) return ret @@ -148,26 +155,25 @@ func produceMessages(ctx context.Context, msgs []string, producer *Producer[test return promises, nil } -func awaitResponses(ctx context.Context, promises []*containers.Promise[testResponse]) ([]string, error) { +func awaitResponses(ctx context.Context, promises []*containers.Promise[testResponse]) ([]string, []int) { var ( responses []string - errs []error + errs []int ) - for _, p := range promises { + for idx, p := range promises { res, err := p.Await(ctx) if err != nil { - errs = append(errs, err) + errs = append(errs, idx) continue } responses = append(responses, res.Response) } - return responses, errors.Join(errs...) + return responses, errs } // consume messages from every consumer except stopped ones. -func consume(ctx context.Context, t *testing.T, consumers []*Consumer[testRequest, testResponse]) ([]map[string]string, [][]string) { +func consume(ctx context.Context, t *testing.T, consumers []*Consumer[testRequest, testResponse], gotMessages []map[string]string) [][]string { t.Helper() - gotMessages := messagesMaps(consumersCount) wantResponses := make([][]string, consumersCount) for idx := 0; idx < consumersCount; idx++ { if consumers[idx].Stopped() { @@ -199,7 +205,7 @@ func consume(ctx context.Context, t *testing.T, consumers []*Consumer[testReques } }) } - return gotMessages, wantResponses + return wantResponses } func TestRedisProduce(t *testing.T) { @@ -208,43 +214,56 @@ func TestRedisProduce(t *testing.T) { for _, tc := range []struct { name string killConsumers bool + autoRecover bool }{ { name: "all consumers are active", killConsumers: false, + autoRecover: false, }, { name: "some consumers killed, others should take over their work", killConsumers: true, + autoRecover: true, + }, + { + name: "some consumers killed, should return failure", + killConsumers: true, + autoRecover: false, }, } { t.Run(tc.name, func(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - producer, consumers := newProducerConsumers(ctx, t) + redisClient, streamName, producer, consumers := newProducerConsumers(ctx, t, &withReproduce{tc.autoRecover}) producer.Start(ctx) wantMsgs := wantMessages(messagesCount) promises, err := produceMessages(ctx, wantMsgs, producer) if err != nil { t.Fatalf("Error producing messages: %v", err) } + gotMessages := messagesMaps(len(consumers)) if tc.killConsumers { // Consumer messages in every third consumer but don't ack them to check // that other consumers will claim ownership on those messages. for i := 0; i < len(consumers); i += 3 { consumers[i].Start(ctx) - if _, err := consumers[i].Consume(ctx); err != nil { + req, err := consumers[i].Consume(ctx) + if err != nil { t.Errorf("Error consuming message: %v", err) } + if !tc.autoRecover { + gotMessages[i][req.ID] = req.Value.Request + } consumers[i].StopAndWait() } } time.Sleep(time.Second) - gotMessages, wantResponses := consume(ctx, t, consumers) - gotResponses, err := awaitResponses(ctx, promises) - if err != nil { - t.Fatalf("Error awaiting responses: %v", err) + wantResponses := consume(ctx, t, consumers, gotMessages) + gotResponses, errIndexes := awaitResponses(ctx, promises) + if len(errIndexes) != 0 && tc.autoRecover { + t.Fatalf("Error awaiting responses: %v", errIndexes) } producer.StopAndWait() for _, c := range consumers { @@ -254,7 +273,6 @@ func TestRedisProduce(t *testing.T) { if err != nil { t.Fatalf("mergeMaps() unexpected error: %v", err) } - if diff := cmp.Diff(wantMsgs, got); diff != "" { t.Errorf("Unexpected diff (-want +got):\n%s\n", diff) } @@ -266,57 +284,19 @@ func TestRedisProduce(t *testing.T) { if cnt := producer.promisesLen(); cnt != 0 { t.Errorf("Producer still has %d unfullfilled promises", cnt) } + // Trigger a trim + producer.checkResponses(ctx) + msgs, err := redisClient.XRange(ctx, streamName, "-", "+").Result() + if err != nil { + t.Errorf("XRange failed: %v", err) + } + if len(msgs) != 0 { + t.Errorf("redis still has %v messages", len(msgs)) + } }) } } -func TestRedisReproduceDisabled(t *testing.T) { - t.Parallel() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - producer, consumers := newProducerConsumers(ctx, t, &disableReproduce{}) - producer.Start(ctx) - wantMsgs := wantMessages(messagesCount) - promises, err := produceMessages(ctx, wantMsgs, producer) - if err != nil { - t.Fatalf("Error producing messages: %v", err) - } - - // Consumer messages in every third consumer but don't ack them to check - // that other consumers will claim ownership on those messages. - for i := 0; i < len(consumers); i += 3 { - consumers[i].Start(ctx) - if _, err := consumers[i].Consume(ctx); err != nil { - t.Errorf("Error consuming message: %v", err) - } - consumers[i].StopAndWait() - } - - gotMessages, _ := consume(ctx, t, consumers) - gotResponses, err := awaitResponses(ctx, promises) - if err == nil { - t.Fatalf("All promises were fullfilled with reproduce disabled and some consumers killed") - } - producer.StopAndWait() - for _, c := range consumers { - c.StopWaiter.StopAndWait() - } - got, err := mergeValues(gotMessages) - if err != nil { - t.Fatalf("mergeMaps() unexpected error: %v", err) - } - wantMsgCnt := messagesCount - ((consumersCount + 2) / 3) - if len(got) != wantMsgCnt { - t.Fatalf("Got: %d messages, want %d", len(got), wantMsgCnt) - } - if len(gotResponses) != wantMsgCnt { - t.Errorf("Got %d responses want: %d\n", len(gotResponses), wantMsgCnt) - } - if cnt := producer.promisesLen(); cnt != 0 { - t.Errorf("Producer still has %d unfullfilled promises", cnt) - } -} - // mergeValues merges maps from the slice and returns their values. // Returns and error if there exists duplicate key. func mergeValues(messages []map[string]string) ([]string, error) { diff --git a/safe-smart-account b/safe-smart-account new file mode 160000 index 0000000000..192c7dc672 --- /dev/null +++ b/safe-smart-account @@ -0,0 +1 @@ +Subproject commit 192c7dc67290940fcbc75165522bb86a37187069 diff --git a/solgen/gen.go b/solgen/gen.go index 92511595d7..2ad71b0c79 100644 --- a/solgen/gen.go +++ b/solgen/gen.go @@ -73,6 +73,18 @@ func main() { log.Fatal(err) } + filePathsSafeSmartAccount, err := filepath.Glob(filepath.Join(parent, "safe-smart-account", "build", "artifacts", "contracts", "*", "*.sol", "*.json")) + if err != nil { + log.Fatal(err) + } + filePathsSafeSmartAccountOuter, err := filepath.Glob(filepath.Join(parent, "safe-smart-account", "build", "artifacts", "contracts", "*.sol", "*.json")) + if err != nil { + log.Fatal(err) + } + + filePaths = append(filePaths, filePathsSafeSmartAccount...) + filePaths = append(filePaths, filePathsSafeSmartAccountOuter...) + modules := make(map[string]*moduleInfo) for _, path := range filePaths { diff --git a/staker/block_validator.go b/staker/block_validator.go index d7b5f4f6a2..fc9f21cf42 100644 --- a/staker/block_validator.go +++ b/staker/block_validator.go @@ -34,7 +34,14 @@ var ( validatorPendingValidationsGauge = metrics.NewRegisteredGauge("arb/validator/validations/pending", nil) validatorValidValidationsCounter = metrics.NewRegisteredCounter("arb/validator/validations/valid", nil) validatorFailedValidationsCounter = metrics.NewRegisteredCounter("arb/validator/validations/failed", nil) + validatorProfileWaitToRecordHist = metrics.NewRegisteredHistogram("arb/validator/profile/wait_to_record", nil, metrics.NewBoundedHistogramSample()) + validatorProfileRecordingHist = metrics.NewRegisteredHistogram("arb/validator/profile/recording", nil, metrics.NewBoundedHistogramSample()) + validatorProfileWaitToLaunchHist = metrics.NewRegisteredHistogram("arb/validator/profile/wait_to_launch", nil, metrics.NewBoundedHistogramSample()) + validatorProfileLaunchingHist = metrics.NewRegisteredHistogram("arb/validator/profile/launching", nil, metrics.NewBoundedHistogramSample()) + validatorProfileRunningHist = metrics.NewRegisteredHistogram("arb/validator/profile/running", nil, metrics.NewBoundedHistogramSample()) validatorMsgCountCurrentBatch = metrics.NewRegisteredGauge("arb/validator/msg_count_current_batch", nil) + validatorMsgCountCreatedGauge = metrics.NewRegisteredGauge("arb/validator/msg_count_created", nil) + validatorMsgCountRecordSentGauge = metrics.NewRegisteredGauge("arb/validator/msg_count_record_sent", nil) validatorMsgCountValidatedGauge = metrics.NewRegisteredGauge("arb/validator/msg_count_validated", nil) ) @@ -208,10 +215,11 @@ const ( ) type validationStatus struct { - Status atomic.Uint32 // atomic: value is one of validationStatus* - Cancel func() // non-atomic: only read/written to with reorg mutex - Entry *validationEntry // non-atomic: only read if Status >= validationStatusPrepared - Runs []validator.ValidationRun // if status >= ValidationSent + Status atomic.Uint32 // atomic: value is one of validationStatus* + Cancel func() // non-atomic: only read/written to with reorg mutex + Entry *validationEntry // non-atomic: only read if Status >= validationStatusPrepared + Runs []validator.ValidationRun // if status >= ValidationSent + profileTS int64 // time-stamp for profiling } func (s *validationStatus) getStatus() valStatusField { @@ -223,6 +231,13 @@ func (s *validationStatus) replaceStatus(old, new valStatusField) bool { return s.Status.CompareAndSwap(uint32(old), uint32(new)) } +// gets how many miliseconds last step took, and starts measuring a new step +func (s *validationStatus) profileStep() int64 { + start := s.profileTS + s.profileTS = time.Now().UnixMilli() + return s.profileTS - start +} + func NewBlockValidator( statelessBlockValidator *StatelessBlockValidator, inbox InboxTrackerInterface, @@ -283,8 +298,9 @@ func NewBlockValidator( return ret, nil } -func atomicStorePos(addr *atomic.Uint64, val arbutil.MessageIndex) { +func atomicStorePos(addr *atomic.Uint64, val arbutil.MessageIndex, metr metrics.Gauge) { addr.Store(uint64(val)) + metr.Update(int64(val)) } func atomicLoadPos(addr *atomic.Uint64) arbutil.MessageIndex { @@ -444,6 +460,8 @@ func (v *BlockValidator) sendRecord(s *validationStatus) error { if !s.replaceStatus(Created, RecordSent) { return fmt.Errorf("failed status check for send record. Status: %v", s.getStatus()) } + + validatorProfileWaitToRecordHist.Update(s.profileStep()) v.LaunchThread(func(ctx context.Context) { err := v.ValidationEntryRecord(ctx, s.Entry) if ctx.Err() != nil { @@ -454,6 +472,7 @@ func (v *BlockValidator) sendRecord(s *validationStatus) error { log.Error("Error while recording", "err", err, "status", s.getStatus()) return } + validatorProfileRecordingHist.Update(s.profileStep()) if !s.replaceStatus(RecordSent, Prepared) { log.Error("Fault trying to update validation with recording", "entry", s.Entry, "status", s.getStatus()) return @@ -465,7 +484,7 @@ func (v *BlockValidator) sendRecord(s *validationStatus) error { //nolint:gosec func (v *BlockValidator) writeToFile(validationEntry *validationEntry, moduleRoot common.Hash) error { - input, err := validationEntry.ToInput() + input, err := validationEntry.ToInput([]string{"wavm"}) if err != nil { return err } @@ -506,25 +525,6 @@ func (v *BlockValidator) SetCurrentWasmModuleRoot(hash common.Hash) error { ) } -func (v *BlockValidator) readBatch(ctx context.Context, batchNum uint64) (bool, []byte, common.Hash, arbutil.MessageIndex, error) { - batchCount, err := v.inboxTracker.GetBatchCount() - if err != nil { - return false, nil, common.Hash{}, 0, err - } - if batchCount <= batchNum { - return false, nil, common.Hash{}, 0, nil - } - batchMsgCount, err := v.inboxTracker.GetBatchMessageCount(batchNum) - if err != nil { - return false, nil, common.Hash{}, 0, err - } - batch, batchBlockHash, err := v.inboxReader.GetSequencerMessageBytes(ctx, batchNum) - if err != nil { - return false, nil, common.Hash{}, 0, err - } - return true, batch, batchBlockHash, batchMsgCount, nil -} - func (v *BlockValidator) createNextValidationEntry(ctx context.Context) (bool, error) { v.reorgMutex.RLock() defer v.reorgMutex.RUnlock() @@ -582,13 +582,14 @@ func (v *BlockValidator) createNextValidationEntry(ctx context.Context) (bool, e return false, err } status := &validationStatus{ - Entry: entry, + Entry: entry, + profileTS: time.Now().UnixMilli(), } status.Status.Store(uint32(Created)) v.validations.Store(pos, status) v.nextCreateStartGS = endGS v.nextCreatePrevDelayed = msg.DelayedMessagesRead - atomicStorePos(&v.createdA, pos+1) + atomicStorePos(&v.createdA, pos+1, validatorMsgCountCreatedGauge) log.Trace("create validation entry: created", "pos", pos) return true, nil } @@ -667,7 +668,7 @@ func (v *BlockValidator) sendNextRecordRequests(ctx context.Context) (bool, erro return false, err } pos += 1 - atomicStorePos(&v.recordSentA, pos) + atomicStorePos(&v.recordSentA, pos, validatorMsgCountRecordSentGauge) log.Trace("next record request: sent", "pos", pos) } @@ -778,11 +779,10 @@ validationsLoop: log.Error("failed writing new validated to database", "pos", pos, "err", err) } go v.recorder.MarkValid(pos, v.lastValidGS.BlockHash) - atomicStorePos(&v.validatedA, pos+1) + atomicStorePos(&v.validatedA, pos+1, validatorMsgCountValidatedGauge) v.validations.Delete(pos) nonBlockingTrigger(v.createNodesChan) nonBlockingTrigger(v.sendRecordChan) - validatorMsgCountValidatedGauge.Update(int64(pos + 1)) if v.testingProgressMadeChan != nil { nonBlockingTrigger(v.testingProgressMadeChan) } @@ -790,12 +790,13 @@ validationsLoop: continue } for _, moduleRoot := range wasmRoots { - if v.chosenValidator[moduleRoot] == nil { + spawner := v.chosenValidator[moduleRoot] + if spawner == nil { notFoundErr := fmt.Errorf("did not find spawner for moduleRoot :%v", moduleRoot) v.possiblyFatal(notFoundErr) return nil, notFoundErr } - if v.chosenValidator[moduleRoot].Room() == 0 { + if spawner.Room() == 0 { log.Trace("advanceValidations: no more room", "moduleRoot", moduleRoot) return nil, nil } @@ -805,28 +806,35 @@ validationsLoop: return nil, nil } if currentStatus == Prepared { - input, err := validationStatus.Entry.ToInput() - if err != nil && ctx.Err() == nil { - v.possiblyFatal(fmt.Errorf("%w: error preparing validation", err)) - continue - } replaced := validationStatus.replaceStatus(Prepared, SendingValidation) if !replaced { v.possiblyFatal(errors.New("failed to set SendingValidation status")) } + validatorProfileWaitToLaunchHist.Update(validationStatus.profileStep()) validatorPendingValidationsGauge.Inc(1) var runs []validator.ValidationRun for _, moduleRoot := range wasmRoots { - run := v.chosenValidator[moduleRoot].Launch(input, moduleRoot) + spawner := v.chosenValidator[moduleRoot] + input, err := validationStatus.Entry.ToInput(spawner.StylusArchs()) + if err != nil && ctx.Err() == nil { + v.possiblyFatal(fmt.Errorf("%w: error preparing validation", err)) + continue + } + if ctx.Err() != nil { + return nil, ctx.Err() + } + run := spawner.Launch(input, moduleRoot) log.Trace("advanceValidations: launched", "pos", validationStatus.Entry.Pos, "moduleRoot", moduleRoot) runs = append(runs, run) } + validatorProfileLaunchingHist.Update(validationStatus.profileStep()) validationCtx, cancel := context.WithCancel(ctx) validationStatus.Runs = runs validationStatus.Cancel = cancel v.LaunchUntrackedThread(func() { defer validatorPendingValidationsGauge.Dec(1) defer cancel() + startTsMilli := validationStatus.profileTS replaced = validationStatus.replaceStatus(SendingValidation, ValidationSent) if !replaced { v.possiblyFatal(errors.New("failed to set status to ValidationSent")) @@ -840,6 +848,7 @@ validationsLoop: return } } + validatorProfileRunningHist.Update(time.Now().UnixMilli() - startTsMilli) nonBlockingTrigger(v.progressValidationsChan) }) } @@ -1222,9 +1231,9 @@ func (v *BlockValidator) checkValidatedGSCaughtUp() (bool, error) { v.nextCreateBatchReread = true v.nextCreateStartGS = v.lastValidGS v.nextCreatePrevDelayed = msg.DelayedMessagesRead - atomicStorePos(&v.createdA, count) - atomicStorePos(&v.recordSentA, count) - atomicStorePos(&v.validatedA, count) + atomicStorePos(&v.createdA, count, validatorMsgCountCreatedGauge) + atomicStorePos(&v.recordSentA, count, validatorMsgCountRecordSentGauge) + atomicStorePos(&v.validatedA, count, validatorMsgCountValidatedGauge) validatorMsgCountValidatedGauge.Update(int64(count)) v.chainCaughtUp = true return true, nil diff --git a/staker/challenge_manager.go b/staker/challenge_manager.go index 22897e3c1d..80cafccced 100644 --- a/staker/challenge_manager.go +++ b/staker/challenge_manager.go @@ -467,7 +467,7 @@ func (m *ChallengeManager) createExecutionBackend(ctx context.Context, step uint if err != nil { return fmt.Errorf("error creating validation entry for challenge %v msg %v for execution challenge: %w", m.challengeIndex, initialCount, err) } - input, err := entry.ToInput() + input, err := entry.ToInput([]string{"wavm"}) if err != nil { return fmt.Errorf("error getting validation entry input of challenge %v msg %v: %w", m.challengeIndex, initialCount, err) } diff --git a/staker/fast_confirm.go b/staker/fast_confirm.go new file mode 100644 index 0000000000..7ae620838b --- /dev/null +++ b/staker/fast_confirm.go @@ -0,0 +1,253 @@ +// Copyright 2023-2024, Offchain Labs, Inc. +// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE + +package staker + +import ( + "context" + "errors" + "fmt" + "math/big" + "sort" + + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/log" + + "github.com/offchainlabs/nitro/solgen/go/contractsgen" + "github.com/offchainlabs/nitro/solgen/go/rollupgen" + "github.com/offchainlabs/nitro/staker/txbuilder" + "github.com/offchainlabs/nitro/util/headerreader" +) + +type FastConfirmSafe struct { + safe *contractsgen.Safe + owners []common.Address + threshold uint64 + fastConfirmNextNodeMethod abi.Method + builder *txbuilder.Builder + wallet ValidatorWalletInterface + gasRefunder common.Address + l1Reader *headerreader.HeaderReader +} + +func NewFastConfirmSafe( + callOpts bind.CallOpts, + fastConfirmSafeAddress common.Address, + builder *txbuilder.Builder, + wallet ValidatorWalletInterface, + gasRefunder common.Address, + l1Reader *headerreader.HeaderReader, +) (*FastConfirmSafe, error) { + fastConfirmSafe := &FastConfirmSafe{ + builder: builder, + wallet: wallet, + gasRefunder: gasRefunder, + l1Reader: l1Reader, + } + safe, err := contractsgen.NewSafe(fastConfirmSafeAddress, builder) + if err != nil { + return nil, err + } + fastConfirmSafe.safe = safe + owners, err := safe.GetOwners(&callOpts) + if err != nil { + return nil, err + } + + // This is needed because safe contract needs owners to be sorted. + sort.Slice(owners, func(i, j int) bool { + return owners[i].Cmp(owners[j]) < 0 + }) + fastConfirmSafe.owners = owners + threshold, err := safe.GetThreshold(&callOpts) + if err != nil { + return nil, err + } + fastConfirmSafe.threshold = threshold.Uint64() + rollupUserLogicAbi, err := rollupgen.RollupUserLogicMetaData.GetAbi() + if err != nil { + return nil, err + } + fastConfirmNextNodeMethod, ok := rollupUserLogicAbi.Methods["fastConfirmNextNode"] + if !ok { + return nil, errors.New("RollupUserLogic ABI missing fastConfirmNextNode method") + } + fastConfirmSafe.fastConfirmNextNodeMethod = fastConfirmNextNodeMethod + return fastConfirmSafe, nil +} + +func (f *FastConfirmSafe) tryFastConfirmation(ctx context.Context, blockHash common.Hash, sendRoot common.Hash, nodeHash common.Hash) error { + if f.wallet.Address() == nil { + return errors.New("fast confirmation requires a wallet which is not setup") + } + fastConfirmCallData, err := f.createFastConfirmCalldata(blockHash, sendRoot, nodeHash) + if err != nil { + return err + } + callOpts := &bind.CallOpts{Context: ctx} + // Current nonce of the safe. + nonce, err := f.safe.Nonce(callOpts) + if err != nil { + return err + } + // Hash of the safe transaction. + safeTxHash, err := f.safe.GetTransactionHash( + callOpts, + f.wallet.RollupAddress(), + big.NewInt(0), + fastConfirmCallData, + 0, + big.NewInt(0), + big.NewInt(0), + big.NewInt(0), + common.Address{}, + common.Address{}, + nonce, + ) + if err != nil { + return err + } + if !f.wallet.CanBatchTxs() { + err = f.flushTransactions(ctx) + if err != nil { + return err + } + } + + alreadyApproved, err := f.safe.ApprovedHashes(&bind.CallOpts{Context: ctx}, *f.wallet.Address(), safeTxHash) + if err != nil { + return err + } + if alreadyApproved.Cmp(common.Big1) == 0 { + _, err = f.checkApprovedHashAndExecTransaction(ctx, fastConfirmCallData, safeTxHash) + return err + } + + auth, err := f.builder.Auth(ctx) + if err != nil { + return err + } + _, err = f.safe.ApproveHash(auth, safeTxHash) + if err != nil { + return err + } + if !f.wallet.CanBatchTxs() { + err = f.flushTransactions(ctx) + if err != nil { + return err + } + } + executedTx, err := f.checkApprovedHashAndExecTransaction(ctx, fastConfirmCallData, safeTxHash) + if err != nil { + return err + } + if executedTx { + return nil + } + // If the transaction was not executed, we need to flush the transactions (for approve hash) and try again. + // This is because the hash might have been approved by another wallet in the same block, + // which might have led to a race condition. + err = f.flushTransactions(ctx) + if err != nil { + return err + } + _, err = f.checkApprovedHashAndExecTransaction(ctx, fastConfirmCallData, safeTxHash) + return err +} + +func (f *FastConfirmSafe) flushTransactions(ctx context.Context) error { + arbTx, err := f.wallet.ExecuteTransactions(ctx, f.builder, f.gasRefunder) + if err != nil { + return err + } + if arbTx != nil { + _, err = f.l1Reader.WaitForTxApproval(ctx, arbTx) + if err == nil { + log.Info("successfully executed staker transaction", "hash", arbTx.Hash()) + } else { + return fmt.Errorf("error waiting for tx receipt: %w", err) + } + } + f.builder.ClearTransactions() + return nil +} + +func (f *FastConfirmSafe) createFastConfirmCalldata( + blockHash common.Hash, sendRoot common.Hash, nodeHash common.Hash, +) ([]byte, error) { + calldata, err := f.fastConfirmNextNodeMethod.Inputs.Pack( + blockHash, + sendRoot, + nodeHash, + ) + if err != nil { + return nil, err + } + fullCalldata := append([]byte{}, f.fastConfirmNextNodeMethod.ID...) + fullCalldata = append(fullCalldata, calldata...) + return fullCalldata, nil +} + +func (f *FastConfirmSafe) checkApprovedHashAndExecTransaction(ctx context.Context, fastConfirmCallData []byte, safeTxHash [32]byte) (bool, error) { + if f.wallet.Address() == nil { + return false, errors.New("wallet address is nil") + } + var signatures []byte + approvedHashCount := uint64(0) + for _, owner := range f.owners { + var approved *big.Int + // No need check if wallet has approved the hash, + // since checkApprovedHashAndExecTransaction is called only after wallet has approved the hash. + if *f.wallet.Address() == owner { + approved = common.Big1 + } else { + var err error + approved, err = f.safe.ApprovedHashes(&bind.CallOpts{Context: ctx}, owner, safeTxHash) + if err != nil { + return false, err + } + } + + // If the owner has approved the hash, we add the signature to the transaction. + // We add the signature in the format r, s, v. + // We set v to 1, as it is the only possible value for a approved hash. + // We set r to the owner's address. + // We set s to the empty hash. + // Refer to the Safe contract for more information. + if approved.Cmp(common.Big1) == 0 { + approvedHashCount++ + v := uint8(1) + r := common.BytesToHash(owner.Bytes()) + s := common.Hash{} + signatures = append(signatures, r.Bytes()...) + signatures = append(signatures, s.Bytes()...) + signatures = append(signatures, v) + } + } + if approvedHashCount >= f.threshold { + auth, err := f.builder.Auth(ctx) + if err != nil { + return false, err + } + _, err = f.safe.ExecTransaction( + auth, + f.wallet.RollupAddress(), + big.NewInt(0), + fastConfirmCallData, + 0, + big.NewInt(0), + big.NewInt(0), + big.NewInt(0), + common.Address{}, + common.Address{}, + signatures, + ) + if err != nil { + return false, err + } + return true, nil + } + return false, nil +} diff --git a/staker/staker.go b/staker/staker.go index 24f5dc61e3..3eb941c6dd 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -18,6 +18,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rpc" + "github.com/google/btree" flag "github.com/spf13/pflag" "github.com/offchainlabs/nitro/arbnode/dataposter" @@ -90,6 +91,8 @@ type L1ValidatorConfig struct { ExtraGas uint64 `koanf:"extra-gas" reload:"hot"` Dangerous DangerousConfig `koanf:"dangerous"` ParentChainWallet genericconf.WalletConfig `koanf:"parent-chain-wallet"` + EnableFastConfirmation bool `koanf:"enable-fast-confirmation"` + FastConfirmSafeAddress string `koanf:"fast-confirm-safe-address"` LogQueryBatchSize uint64 `koanf:"log-query-batch-size" reload:"hot"` strategy StakerStrategy @@ -157,6 +160,8 @@ var DefaultL1ValidatorConfig = L1ValidatorConfig{ ExtraGas: 50000, Dangerous: DefaultDangerousConfig, ParentChainWallet: DefaultValidatorL1WalletConfig, + EnableFastConfirmation: false, + FastConfirmSafeAddress: "", LogQueryBatchSize: 0, } @@ -178,6 +183,8 @@ var TestL1ValidatorConfig = L1ValidatorConfig{ ExtraGas: 50000, Dangerous: DefaultDangerousConfig, ParentChainWallet: DefaultValidatorL1WalletConfig, + EnableFastConfirmation: false, + FastConfirmSafeAddress: "", LogQueryBatchSize: 0, } @@ -208,6 +215,8 @@ func L1ValidatorConfigAddOptions(prefix string, f *flag.FlagSet) { dataposter.DataPosterConfigAddOptions(prefix+".data-poster", f, dataposter.DefaultDataPosterConfigForValidator) DangerousConfigAddOptions(prefix+".dangerous", f) genericconf.WalletConfigAddOptions(prefix+".parent-chain-wallet", f, DefaultL1ValidatorConfig.ParentChainWallet.Pathname) + f.Bool(prefix+".enable-fast-confirmation", DefaultL1ValidatorConfig.EnableFastConfirmation, "enable fast confirmation") + f.String(prefix+".fast-confirm-safe-address", DefaultL1ValidatorConfig.FastConfirmSafeAddress, "safe address for fast confirmation") } type DangerousConfig struct { @@ -238,6 +247,11 @@ type LatestConfirmedNotifier interface { UpdateLatestConfirmed(count arbutil.MessageIndex, globalState validator.GoGlobalState) } +type validatedNode struct { + number uint64 + hash common.Hash +} + type Staker struct { *L1Validator stopwaiter.StopWaiter @@ -250,10 +264,12 @@ type Staker struct { highGasBlocksBuffer *big.Int lastActCalledBlock *big.Int inactiveLastCheckedNode *nodeAndHash + inactiveValidatedNodes *btree.BTreeG[validatedNode] bringActiveUntilNode uint64 inboxReader InboxReaderInterface statelessBlockValidator *StatelessBlockValidator fatalErr chan<- error + fastConfirmSafe *FastConfirmSafe } type ValidatorWalletInterface interface { @@ -303,6 +319,23 @@ func NewStaker( if config.StartValidationFromStaked && blockValidator != nil { stakedNotifiers = append(stakedNotifiers, blockValidator) } + var fastConfirmSafe *FastConfirmSafe + if config.EnableFastConfirmation && config.FastConfirmSafeAddress != "" { + fastConfirmSafe, err = NewFastConfirmSafe( + callOpts, + common.HexToAddress(config.FastConfirmSafeAddress), + val.builder, + wallet, + config.gasRefunder, + l1Reader, + ) + if err != nil { + return nil, err + } + } + inactiveValidatedNodes := btree.NewG(2, func(a, b validatedNode) bool { + return a.number < b.number || (a.number == b.number && a.hash.Cmp(b.hash) < 0) + }) return &Staker{ L1Validator: val, l1Reader: l1Reader, @@ -315,6 +348,8 @@ func NewStaker( inboxReader: statelessBlockValidator.inboxReader, statelessBlockValidator: statelessBlockValidator, fatalErr: fatalErr, + fastConfirmSafe: fastConfirmSafe, + inactiveValidatedNodes: inactiveValidatedNodes, }, nil } @@ -347,6 +382,32 @@ func (s *Staker) Initialize(ctx context.Context) error { return nil } +func (s *Staker) tryFastConfirmationNodeNumber(ctx context.Context, number uint64, hash common.Hash) error { + if !s.config.EnableFastConfirmation { + return nil + } + nodeInfo, err := s.rollup.LookupNode(ctx, number) + if err != nil { + return err + } + return s.tryFastConfirmation(ctx, nodeInfo.AfterState().GlobalState.BlockHash, nodeInfo.AfterState().GlobalState.SendRoot, hash) +} + +func (s *Staker) tryFastConfirmation(ctx context.Context, blockHash common.Hash, sendRoot common.Hash, nodeHash common.Hash) error { + if !s.config.EnableFastConfirmation { + return nil + } + if s.fastConfirmSafe != nil { + return s.fastConfirmSafe.tryFastConfirmation(ctx, blockHash, sendRoot, nodeHash) + } + auth, err := s.builder.Auth(ctx) + if err != nil { + return err + } + _, err = s.rollup.FastConfirmNextNode(auth, blockHash, sendRoot, nodeHash) + return err +} + func (s *Staker) getLatestStakedState(ctx context.Context, staker common.Address) (uint64, arbutil.MessageIndex, *validator.GoGlobalState, error) { callOpts := s.getCallOpts(ctx) if s.l1Reader.UseFinalityData() { @@ -661,11 +722,68 @@ func (s *Staker) Act(ctx context.Context) (*types.Transaction, error) { info.LatestStakedNodeHash = s.inactiveLastCheckedNode.hash } + if s.config.EnableFastConfirmation { + firstUnresolvedNode, err := s.rollup.FirstUnresolvedNode(callOpts) + if err != nil { + return nil, err + } + if info.LatestStakedNode >= firstUnresolvedNode { + lastHeader, err := s.l1Reader.LastHeader(ctx) + if err != nil { + return nil, err + } + // To check if a node is correct, we simply check if we're staked on it. + // Since we're staked on it or a later node, this will tell us if it's correct. + // To keep this call consistent with the GetNode call, we pin a specific parent chain block hash. + checkNodeCorrectCallOpts := s.getCallOpts(ctx) + checkNodeCorrectCallOpts.BlockHash = lastHeader.ParentHash + nodeInfo, err := s.rollup.GetNode(checkNodeCorrectCallOpts, firstUnresolvedNode) + if err != nil { + return nil, err + } + validatedNode, haveValidated := s.inactiveValidatedNodes.Get(validatedNode{ + number: firstUnresolvedNode, + hash: nodeInfo.NodeHash, + }) + confirmedCorrect := haveValidated && validatedNode.hash == nodeInfo.NodeHash + if !confirmedCorrect { + stakedOnNode, err := s.rollup.NodeHasStaker(checkNodeCorrectCallOpts, firstUnresolvedNode, walletAddressOrZero) + if err != nil { + return nil, err + } + confirmedCorrect = stakedOnNode + } + if confirmedCorrect { + err = s.tryFastConfirmationNodeNumber(ctx, firstUnresolvedNode, nodeInfo.NodeHash) + if err != nil { + return nil, err + } + if s.builder.BuildingTransactionCount() > 0 { + // Try to fast confirm previous nodes before working on new ones + log.Info("fast confirming previous node", "node", firstUnresolvedNode) + return s.wallet.ExecuteTransactions(ctx, s.builder, s.config.gasRefunder) + } + } + } + } + latestConfirmedNode, err := s.rollup.LatestConfirmed(callOpts) if err != nil { return nil, fmt.Errorf("error getting latest confirmed node: %w", err) } + // Clear s.inactiveValidatedNodes of any entries before or equal to latestConfirmedNode + for { + validatedNode, ok := s.inactiveValidatedNodes.Min() + if !ok { + break + } + if validatedNode.number > latestConfirmedNode { + break + } + s.inactiveValidatedNodes.DeleteMin() + } + requiredStakeElevated, err := s.isRequiredStakeElevated(ctx) if err != nil { return nil, fmt.Errorf("error checking if required stake is elevated: %w", err) @@ -850,6 +968,7 @@ func (s *Staker) advanceStake(ctx context.Context, info *OurStakerInfo, effectiv s.bringActiveUntilNode = info.LatestStakedNode + 1 } info.CanProgress = false + // We can't fast confirm a node that doesn't exist return nil } @@ -868,7 +987,7 @@ func (s *Staker) advanceStake(ctx context.Context, info *OurStakerInfo, effectiv if err != nil { return fmt.Errorf("error staking on new node: %w", err) } - return nil + return s.tryFastConfirmation(ctx, action.assertion.AfterState.GlobalState.BlockHash, action.assertion.AfterState.GlobalState.SendRoot, action.hash) } // If we have no stake yet, we'll put one down @@ -890,7 +1009,7 @@ func (s *Staker) advanceStake(ctx context.Context, info *OurStakerInfo, effectiv return fmt.Errorf("error placing new stake on new node: %w", err) } info.StakeExists = true - return nil + return s.tryFastConfirmation(ctx, action.assertion.AfterState.GlobalState.BlockHash, action.assertion.AfterState.GlobalState.SendRoot, action.hash) case existingNodeAction: info.LatestStakedNode = action.number info.LatestStakedNodeHash = action.hash @@ -904,8 +1023,12 @@ func (s *Staker) advanceStake(ctx context.Context, info *OurStakerInfo, effectiv id: action.number, hash: action.hash, } + s.inactiveValidatedNodes.ReplaceOrInsert(validatedNode{ + number: action.number, + hash: action.hash, + }) } - return nil + return s.tryFastConfirmationNodeNumber(ctx, action.number, action.hash) } log.Info("staking on existing node", "node", action.number) // We'll return early if we already havea stake @@ -918,7 +1041,7 @@ func (s *Staker) advanceStake(ctx context.Context, info *OurStakerInfo, effectiv if err != nil { return fmt.Errorf("error staking on existing node: %w", err) } - return nil + return s.tryFastConfirmationNodeNumber(ctx, action.number, action.hash) } // If we have no stake yet, we'll put one down @@ -939,7 +1062,7 @@ func (s *Staker) advanceStake(ctx context.Context, info *OurStakerInfo, effectiv return fmt.Errorf("error placing new stake on existing node: %w", err) } info.StakeExists = true - return nil + return s.tryFastConfirmationNodeNumber(ctx, action.number, action.hash) default: panic("invalid action type") } diff --git a/staker/stateless_block_validator.go b/staker/stateless_block_validator.go index ec235c4bf5..c8842aedc4 100644 --- a/staker/stateless_block_validator.go +++ b/staker/stateless_block_validator.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "net/url" + "runtime" "testing" "github.com/offchainlabs/nitro/arbstate/daprovider" @@ -49,7 +50,7 @@ type BlockValidatorRegistrer interface { type InboxTrackerInterface interface { BlockValidatorRegistrer - GetDelayedMessageBytes(uint64) ([]byte, error) + GetDelayedMessageBytes(context.Context, uint64) ([]byte, error) GetBatchMessageCount(seqNum uint64) (arbutil.MessageIndex, error) GetBatchAcc(seqNum uint64) (common.Hash, error) GetBatchCount() (uint64, error) @@ -134,21 +135,36 @@ type validationEntry struct { DelayedMsg []byte } -func (e *validationEntry) ToInput() (*validator.ValidationInput, error) { +func (e *validationEntry) ToInput(stylusArchs []string) (*validator.ValidationInput, error) { if e.Stage != Ready { return nil, errors.New("cannot create input from non-ready entry") } - return &validator.ValidationInput{ + res := validator.ValidationInput{ Id: uint64(e.Pos), HasDelayedMsg: e.HasDelayedMsg, DelayedMsgNr: e.DelayedMsgNr, Preimages: e.Preimages, - UserWasms: e.UserWasms, + UserWasms: make(map[string]map[common.Hash][]byte, len(e.UserWasms)), BatchInfo: e.BatchInfo, DelayedMsg: e.DelayedMsg, StartState: e.Start, DebugChain: e.ChainConfig.DebugMode(), - }, nil + } + for _, stylusArch := range stylusArchs { + res.UserWasms[stylusArch] = make(map[common.Hash][]byte) + } + for hash, info := range e.UserWasms { + for _, stylusArch := range stylusArchs { + if stylusArch == "wavm" { + res.UserWasms[stylusArch][hash] = info.Module + } else if stylusArch == runtime.GOARCH { + res.UserWasms[stylusArch][hash] = info.Asm + } else { + return nil, fmt.Errorf("stylusArch not supported by block validator: %v", stylusArch) + } + } + } + return &res, nil } func newValidationEntry( @@ -231,6 +247,25 @@ func NewStatelessBlockValidator( }, nil } +func (v *StatelessBlockValidator) readBatch(ctx context.Context, batchNum uint64) (bool, []byte, common.Hash, arbutil.MessageIndex, error) { + batchCount, err := v.inboxTracker.GetBatchCount() + if err != nil { + return false, nil, common.Hash{}, 0, err + } + if batchCount <= batchNum { + return false, nil, common.Hash{}, 0, nil + } + batchMsgCount, err := v.inboxTracker.GetBatchMessageCount(batchNum) + if err != nil { + return false, nil, common.Hash{}, 0, err + } + batch, batchBlockHash, err := v.inboxReader.GetSequencerMessageBytes(ctx, batchNum) + if err != nil { + return false, nil, common.Hash{}, 0, err + } + return true, batch, batchBlockHash, batchMsgCount, nil +} + func (v *StatelessBlockValidator) ValidationEntryRecord(ctx context.Context, e *validationEntry) error { if e.Stage != ReadyForRecord { return fmt.Errorf("validation entry should be ReadyForRecord, is: %v", e.Stage) @@ -244,7 +279,27 @@ func (v *StatelessBlockValidator) ValidationEntryRecord(ctx context.Context, e * if recording.BlockHash != e.End.BlockHash { return fmt.Errorf("recording failed: pos %d, hash expected %v, got %v", e.Pos, e.End.BlockHash, recording.BlockHash) } - e.BatchInfo = append(e.BatchInfo, recording.BatchInfo...) + // record any additional batch fetching + batchFetcher := func(batchNum uint64) ([]byte, error) { + found, data, hash, _, err := v.readBatch(ctx, batchNum) + if err != nil { + return nil, err + } + if !found { + return nil, errors.New("batch not found") + } + e.BatchInfo = append(e.BatchInfo, validator.BatchInfo{ + Number: batchNum, + BlockHash: hash, + Data: data, + }) + return data, nil + } + e.msg.Message.BatchGasCost = nil + err = e.msg.Message.FillInBatchGasCost(batchFetcher) + if err != nil { + return err + } if recording.Preimages != nil { e.Preimages[arbutil.Keccak256PreimageType] = recording.Preimages @@ -252,7 +307,7 @@ func (v *StatelessBlockValidator) ValidationEntryRecord(ctx context.Context, e * e.UserWasms = recording.UserWasms } if e.HasDelayedMsg { - delayedMsg, err := v.inboxTracker.GetDelayedMessageBytes(e.DelayedMsgNr) + delayedMsg, err := v.inboxTracker.GetDelayedMessageBytes(ctx, e.DelayedMsgNr) if err != nil { log.Error( "error while trying to read delayed msg for proving", @@ -373,14 +428,14 @@ func (v *StatelessBlockValidator) ValidateResult( if err != nil { return false, nil, err } - input, err := entry.ToInput() - if err != nil { - return false, nil, err - } var run validator.ValidationRun if !useExec { if v.redisValidator != nil { if validator.SpawnerSupportsModule(v.redisValidator, moduleRoot) { + input, err := entry.ToInput(v.redisValidator.StylusArchs()) + if err != nil { + return false, nil, err + } run = v.redisValidator.Launch(input, moduleRoot) } } @@ -388,6 +443,10 @@ func (v *StatelessBlockValidator) ValidateResult( if run == nil { for _, spawner := range v.execSpawners { if validator.SpawnerSupportsModule(spawner, moduleRoot) { + input, err := entry.ToInput(spawner.StylusArchs()) + if err != nil { + return false, nil, err + } run = spawner.Launch(input, moduleRoot) break } 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 ccee6aa8e4..d170173cc0 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -6,6 +6,7 @@ package arbtest import ( "bytes" "context" + "encoding/binary" "encoding/hex" "encoding/json" "io" @@ -19,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" @@ -66,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" @@ -75,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" "golang.org/x/exp/slog" ) @@ -151,6 +153,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 @@ -164,12 +234,13 @@ type NodeBuilder struct { L2Info info // L1, L2 Node parameters - dataDir string - isSequencer bool - takeOwnership bool - withL1 bool - addresses *chaininfo.RollupAddresses - initMessage *arbostypes.ParsedInitMessage + dataDir string + isSequencer bool + takeOwnership bool + withL1 bool + addresses *chaininfo.RollupAddresses + initMessage *arbostypes.ParsedInitMessage + withProdConfirmPeriodBlocks bool // Created nodes L1 *TestClient @@ -194,11 +265,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 } @@ -209,6 +280,11 @@ func (b *NodeBuilder) WithArbOSVersion(arbosVersion uint64) *NodeBuilder { return b } +func (b *NodeBuilder) WithProdConfirmPeriodBlocks() *NodeBuilder { + b.withProdConfirmPeriodBlocks = true + return b +} + func (b *NodeBuilder) WithWasmRootDir(wasmRootDir string) *NodeBuilder { b.valnodeConfig.Wasm.RootPath = wasmRootDir return b @@ -231,7 +307,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) @@ -253,7 +329,7 @@ func (b *NodeBuilder) BuildL1(t *testing.T) { b.L1Info, b.L1.Client, b.L1.L1Backend, b.L1.Stack = createTestL1BlockChain(t, b.L1Info) locator, err := server_common.NewMachineLocator(b.valnodeConfig.Wasm.RootPath) Require(t, err) - b.addresses, b.initMessage = DeployOnTestL1(t, b.ctx, b.L1Info, b.L1.Client, b.chainConfig, locator.LatestWasmModuleRoot()) + b.addresses, b.initMessage = DeployOnTestL1(t, b.ctx, b.L1Info, b.L1.Client, b.chainConfig, locator.LatestWasmModuleRoot(), b.withProdConfirmPeriodBlocks) b.L1.cleanup = func() { requireClose(t, b.L1.Stack) } } @@ -544,6 +620,57 @@ func BridgeBalance( return tx, res } +func SendSignedTxesInBatchViaL1( + t *testing.T, + ctx context.Context, + l1info *BlockchainTestInfo, + l1client arbutil.L1Interface, + l2client arbutil.L1Interface, + delayedTxes types.Transactions, +) types.Receipts { + delayedInboxContract, err := bridgegen.NewInbox(l1info.GetAddress("Inbox"), l1client) + Require(t, err) + usertxopts := l1info.GetDefaultTransactOpts("User", ctx) + + wraped, err := l2MessageBatchDataFromTxes(delayedTxes) + Require(t, err) + l1tx, err := delayedInboxContract.SendL2Message(&usertxopts, wraped) + Require(t, err) + _, err = EnsureTxSucceeded(ctx, l1client, l1tx) + Require(t, err) + + // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in + for i := 0; i < 30; i++ { + SendWaitTestTransactions(t, ctx, l1client, []*types.Transaction{ + l1info.PrepareTx("Faucet", "Faucet", 30000, big.NewInt(1e12), nil), + }) + } + var receipts types.Receipts + for _, tx := range delayedTxes { + receipt, err := EnsureTxSucceeded(ctx, l2client, tx) + Require(t, err) + receipts = append(receipts, receipt) + } + return receipts +} + +func l2MessageBatchDataFromTxes(txes types.Transactions) ([]byte, error) { + var l2Message []byte + l2Message = append(l2Message, arbos.L2MessageKind_Batch) + sizeBuf := make([]byte, 8) + for _, tx := range txes { + txBytes, err := tx.MarshalBinary() + if err != nil { + return nil, err + } + binary.BigEndian.PutUint64(sizeBuf, uint64(len(txBytes)+1)) + l2Message = append(l2Message, sizeBuf...) + l2Message = append(l2Message, arbos.L2MessageKind_SignedTx) + l2Message = append(l2Message, txBytes...) + } + return l2Message, nil +} + func SendSignedTxViaL1( t *testing.T, ctx context.Context, @@ -681,23 +808,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. @@ -790,12 +900,12 @@ func AddDefaultValNode(t *testing.T, ctx context.Context, nodeConfig *arbnode.Co conf.Wasm.RootPath = wasmRootDir // Enable redis streams when URL is specified if redisURL != "" { - conf.Arbitrator.RedisValidationServerConfig = rediscons.DefaultValidationServerConfig + conf.Arbitrator.RedisValidationServerConfig = rediscons.TestValidationServerConfig redisClient, err := redisutil.RedisClientFromURL(redisURL) if err != nil { t.Fatalf("Error creating redis coordinator: %v", err) } - redisStream := server_api.RedisStreamForRoot(currentRootModule(t)) + redisStream := server_api.RedisStreamForRoot(rediscons.TestValidationServerConfig.StreamPrefix, currentRootModule(t)) createRedisGroup(ctx, t, redisStream, redisClient) conf.Arbitrator.RedisValidationServerConfig.RedisURL = redisURL t.Cleanup(func() { destroyRedisGroup(ctx, t, redisStream, redisClient) }) @@ -809,7 +919,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() @@ -883,7 +993,7 @@ func getInitMessage(ctx context.Context, t *testing.T, l1client client, addresse } func DeployOnTestL1( - t *testing.T, ctx context.Context, l1info info, l1client client, chainConfig *params.ChainConfig, wasmModuleRoot common.Hash, + t *testing.T, ctx context.Context, l1info info, l1client client, chainConfig *params.ChainConfig, wasmModuleRoot common.Hash, prodConfirmPeriodBlocks bool, ) (*chaininfo.RollupAddresses, *arbostypes.ParsedInitMessage) { l1info.GenerateAccount("RollupOwner") l1info.GenerateAccount("Sequencer") @@ -915,7 +1025,7 @@ func DeployOnTestL1( []common.Address{l1info.GetAddress("Sequencer")}, l1info.GetAddress("RollupOwner"), 0, - arbnode.GenerateRollupConfig(false, wasmModuleRoot, l1info.GetAddress("RollupOwner"), chainConfig, serializedChainConfig, common.Address{}), + arbnode.GenerateRollupConfig(prodConfirmPeriodBlocks, wasmModuleRoot, l1info.GetAddress("RollupOwner"), chainConfig, serializedChainConfig, common.Address{}), nativeToken, maxDataSize, false, @@ -944,7 +1054,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) @@ -972,7 +1082,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 @@ -1025,14 +1135,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) @@ -1055,7 +1165,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) @@ -1194,7 +1304,7 @@ func setupConfigWithDAS( URL: "http://" + rpcLis.Addr().String(), Pubkey: blsPubToBase64(dasSignerKey), } - l1NodeConfigA.DataAvailability.RPCAggregator = aggConfigForBackend(t, beConfigA) + l1NodeConfigA.DataAvailability.RPCAggregator = aggConfigForBackend(beConfigA) l1NodeConfigA.DataAvailability.Enable = true l1NodeConfigA.DataAvailability.RestAggregator = das.DefaultRestfulClientAggregatorConfig l1NodeConfigA.DataAvailability.RestAggregator.Enable = true diff --git a/system_tests/das_test.go b/system_tests/das_test.go index 76ec2d7493..9f4d153b6f 100644 --- a/system_tests/das_test.go +++ b/system_tests/das_test.go @@ -29,6 +29,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" ) @@ -88,7 +89,7 @@ func blsPubToBase64(pubkey *blsSignatures.PublicKey) string { return string(encodedPubkey) } -func aggConfigForBackend(t *testing.T, backendConfig das.BackendConfig) das.AggregatorConfig { +func aggConfigForBackend(backendConfig das.BackendConfig) das.AggregatorConfig { return das.AggregatorConfig{ Enable: true, AssumedHonest: 1, @@ -114,7 +115,7 @@ func TestDASRekey(t *testing.T) { // Setup DAS config builder.nodeConfig.DataAvailability.Enable = true - builder.nodeConfig.DataAvailability.RPCAggregator = aggConfigForBackend(t, backendConfigA) + builder.nodeConfig.DataAvailability.RPCAggregator = aggConfigForBackend(backendConfigA) builder.nodeConfig.DataAvailability.RestAggregator = das.DefaultRestfulClientAggregatorConfig builder.nodeConfig.DataAvailability.RestAggregator.Enable = true builder.nodeConfig.DataAvailability.RestAggregator.Urls = []string{restServerUrlA} @@ -152,8 +153,8 @@ func TestDASRekey(t *testing.T) { authorizeDASKeyset(t, ctx, pubkeyB, builder.L1Info, builder.L1.Client) // 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.nodeConfig.DataAvailability.RPCAggregator = aggConfigForBackend(backendConfigB) + builder.l2StackConfig = testhelpers.CreateStackConfigForTest(builder.dataDir) cleanup := builder.BuildL2OnL1(t) defer cleanup() @@ -267,7 +268,7 @@ func TestDASComplexConfigAndRestMirror(t *testing.T) { URL: "http://" + rpcLis.Addr().String(), Pubkey: blsPubToBase64(pubkey), } - builder.nodeConfig.DataAvailability.RPCAggregator = aggConfigForBackend(t, beConfigA) + builder.nodeConfig.DataAvailability.RPCAggregator = aggConfigForBackend(beConfigA) builder.nodeConfig.DataAvailability.RestAggregator = das.DefaultRestfulClientAggregatorConfig builder.nodeConfig.DataAvailability.RestAggregator.Enable = true builder.nodeConfig.DataAvailability.RestAggregator.Urls = []string{"http://" + restLis.Addr().String()} 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/fast_confirm_test.go b/system_tests/fast_confirm_test.go new file mode 100644 index 0000000000..d780f80414 --- /dev/null +++ b/system_tests/fast_confirm_test.go @@ -0,0 +1,513 @@ +// Copyright 2023-2024, Offchain Labs, Inc. +// For license information, see https://github.com/OffchainLabs/nitro/blob/master/LICENSE + +// race detection makes things slow and miss timeouts +//go:build !race +// +build !race + +package arbtest + +import ( + "context" + "errors" + "math/big" + "strings" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi" + "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/log" + "github.com/ethereum/go-ethereum/params" + + "github.com/offchainlabs/nitro/arbnode" + "github.com/offchainlabs/nitro/arbnode/dataposter/externalsignertest" + "github.com/offchainlabs/nitro/arbnode/dataposter/storage" + "github.com/offchainlabs/nitro/arbos/l2pricing" + "github.com/offchainlabs/nitro/solgen/go/contractsgen" + "github.com/offchainlabs/nitro/solgen/go/proxiesgen" + "github.com/offchainlabs/nitro/solgen/go/rollupgen" + "github.com/offchainlabs/nitro/solgen/go/upgrade_executorgen" + "github.com/offchainlabs/nitro/staker" + "github.com/offchainlabs/nitro/staker/validatorwallet" + "github.com/offchainlabs/nitro/util" + "github.com/offchainlabs/nitro/validator/valnode" +) + +func TestFastConfirmation(t *testing.T) { + ctx, cancelCtx := context.WithCancel(context.Background()) + defer cancelCtx() + srv := externalsignertest.NewServer(t) + go func() { + if err := srv.Start(); err != nil { + log.Error("Failed to start external signer server:", err) + return + } + }() + var transferGas = util.NormalizeL2GasForL1GasInitial(800_000, params.GWei) // include room for aggregator L1 costs + + builder := NewNodeBuilder(ctx).DefaultConfig(t, true).WithProdConfirmPeriodBlocks() + builder.L2Info = NewBlockChainTestInfo( + t, + types.NewArbitrumSigner(types.NewLondonSigner(builder.chainConfig.ChainID)), big.NewInt(l2pricing.InitialBaseFeeWei*2), + transferGas, + ) + + builder.nodeConfig.BatchPoster.MaxDelay = -1000 * time.Hour + cleanup := builder.Build(t) + defer cleanup() + + addNewBatchPoster(ctx, t, builder, srv.Address) + + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L1Info.PrepareTxTo("Faucet", &srv.Address, 30000, big.NewInt(1).Mul(big.NewInt(1e18), big.NewInt(1e18)), nil)}) + + l2node := builder.L2.ConsensusNode + execNode := builder.L2.ExecNode + + config := arbnode.ConfigDefaultL1Test() + config.Sequencer = false + config.DelayedSequencer.Enable = false + config.BatchPoster.Enable = false + builder.execConfig.Sequencer.Enable = false + + builder.BridgeBalance(t, "Faucet", big.NewInt(1).Mul(big.NewInt(params.Ether), big.NewInt(10000))) + + deployAuth := builder.L1Info.GetDefaultTransactOpts("RollupOwner", ctx) + + balance := big.NewInt(params.Ether) + balance.Mul(balance, big.NewInt(100)) + builder.L1.TransferBalance(t, "Faucet", "Validator", balance, builder.L1Info) + l1auth := builder.L1Info.GetDefaultTransactOpts("Validator", ctx) + + valWalletAddrPtr, err := validatorwallet.GetValidatorWalletContract(ctx, l2node.DeployInfo.ValidatorWalletCreator, 0, &l1auth, l2node.L1Reader, true) + Require(t, err) + valWalletAddr := *valWalletAddrPtr + valWalletAddrCheck, err := validatorwallet.GetValidatorWalletContract(ctx, l2node.DeployInfo.ValidatorWalletCreator, 0, &l1auth, l2node.L1Reader, true) + Require(t, err) + if valWalletAddr == *valWalletAddrCheck { + Require(t, err, "didn't cache validator wallet address", valWalletAddr.String(), "vs", valWalletAddrCheck.String()) + } + + rollup, err := rollupgen.NewRollupAdminLogic(l2node.DeployInfo.Rollup, builder.L1.Client) + Require(t, err) + + upgradeExecutor, err := upgrade_executorgen.NewUpgradeExecutor(l2node.DeployInfo.UpgradeExecutor, builder.L1.Client) + Require(t, err, "unable to bind upgrade executor") + rollupABI, err := abi.JSON(strings.NewReader(rollupgen.RollupAdminLogicABI)) + Require(t, err, "unable to parse rollup ABI") + + setValidatorCalldata, err := rollupABI.Pack("setValidator", []common.Address{valWalletAddr, srv.Address}, []bool{true, true}) + Require(t, err, "unable to generate setValidator calldata") + tx, err := upgradeExecutor.ExecuteCall(&deployAuth, l2node.DeployInfo.Rollup, setValidatorCalldata) + Require(t, err, "unable to set validators") + _, err = builder.L1.EnsureTxSucceeded(tx) + Require(t, err) + + setMinAssertPeriodCalldata, err := rollupABI.Pack("setMinimumAssertionPeriod", big.NewInt(1)) + Require(t, err, "unable to generate setMinimumAssertionPeriod calldata") + tx, err = upgradeExecutor.ExecuteCall(&deployAuth, l2node.DeployInfo.Rollup, setMinAssertPeriodCalldata) + Require(t, err, "unable to set minimum assertion period") + _, err = builder.L1.EnsureTxSucceeded(tx) + Require(t, err) + + setAnyTrustFastConfirmerCalldata, err := rollupABI.Pack("setAnyTrustFastConfirmer", valWalletAddr) + Require(t, err, "unable to generate setAnyTrustFastConfirmer calldata") + tx, err = upgradeExecutor.ExecuteCall(&deployAuth, l2node.DeployInfo.Rollup, setAnyTrustFastConfirmerCalldata) + Require(t, err, "unable to set anytrust fast confirmer") + _, err = builder.L1.EnsureTxSucceeded(tx) + Require(t, err) + + valConfig := staker.TestL1ValidatorConfig + valConfig.EnableFastConfirmation = true + parentChainID, err := builder.L1.Client.ChainID(ctx) + if err != nil { + t.Fatalf("Failed to get parent chain id: %v", err) + } + dp, err := arbnode.StakerDataposter( + ctx, + rawdb.NewTable(l2node.ArbDB, storage.StakerPrefix), + l2node.L1Reader, + &l1auth, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), + nil, + parentChainID, + ) + if err != nil { + t.Fatalf("Error creating validator dataposter: %v", err) + } + valWallet, err := validatorwallet.NewContract(dp, nil, l2node.DeployInfo.ValidatorWalletCreator, l2node.DeployInfo.Rollup, l2node.L1Reader, &l1auth, 0, func(common.Address) {}, func() uint64 { return valConfig.ExtraGas }) + Require(t, err) + valConfig.Strategy = "MakeNodes" + + _, valStack := createTestValidationNode(t, ctx, &valnode.TestValidationConfig) + blockValidatorConfig := staker.TestBlockValidatorConfig + + stateless, err := staker.NewStatelessBlockValidator( + l2node.InboxReader, + l2node.InboxTracker, + l2node.TxStreamer, + execNode, + l2node.ArbDB, + nil, + StaticFetcherFrom(t, &blockValidatorConfig), + valStack, + ) + Require(t, err) + err = stateless.Start(ctx) + Require(t, err) + stakerA, err := staker.NewStaker( + l2node.L1Reader, + valWallet, + bind.CallOpts{}, + valConfig, + nil, + stateless, + nil, + nil, + l2node.DeployInfo.ValidatorUtils, + nil, + ) + Require(t, err) + err = stakerA.Initialize(ctx) + if stakerA.Strategy() != staker.WatchtowerStrategy { + err = valWallet.Initialize(ctx) + Require(t, err) + } + Require(t, err) + cfg := arbnode.ConfigDefaultL1NonSequencerTest() + signerCfg, err := externalSignerTestCfg(srv.Address, srv.URL()) + if err != nil { + t.Fatalf("Error getting external signer config: %v", err) + } + cfg.Staker.DataPoster.ExternalSigner = *signerCfg + + builder.L2Info.GenerateAccount("BackgroundUser") + tx = builder.L2Info.PrepareTx("Faucet", "BackgroundUser", builder.L2Info.TransferGas, balance, nil) + err = builder.L2.Client.SendTransaction(ctx, tx) + Require(t, err) + _, err = builder.L2.EnsureTxSucceeded(tx) + Require(t, err) + + // Continually make L2 transactions in a background thread + backgroundTxsCtx, cancelBackgroundTxs := context.WithCancel(ctx) + backgroundTxsShutdownChan := make(chan struct{}) + defer (func() { + cancelBackgroundTxs() + <-backgroundTxsShutdownChan + })() + go (func() { + defer close(backgroundTxsShutdownChan) + err := makeBackgroundTxs(backgroundTxsCtx, builder) + if !errors.Is(err, context.Canceled) { + log.Warn("error making background txs", "err", err) + } + })() + + latestConfirmBeforeAct, err := rollup.LatestConfirmed(&bind.CallOpts{}) + Require(t, err) + tx, err = stakerA.Act(ctx) + Require(t, err) + if tx != nil { + _, err = builder.L1.EnsureTxSucceeded(tx) + Require(t, err) + } + latestConfirmAfterAct, err := rollup.LatestConfirmed(&bind.CallOpts{}) + Require(t, err) + if latestConfirmAfterAct <= latestConfirmBeforeAct { + Fatal(t, "staker A didn't advance the latest confirmed node") + } +} + +func TestFastConfirmationWithSafe(t *testing.T) { + ctx, cancelCtx := context.WithCancel(context.Background()) + defer cancelCtx() + srv := externalsignertest.NewServer(t) + go func() { + if err := srv.Start(); err != nil { + log.Error("Failed to start external signer server:", err) + return + } + }() + var transferGas = util.NormalizeL2GasForL1GasInitial(800_000, params.GWei) // include room for aggregator L1 costs + + // Create a node with a large confirm period to ensure that the staker can't confirm without the fast confirmer. + builder := NewNodeBuilder(ctx).DefaultConfig(t, true).WithProdConfirmPeriodBlocks() + builder.L2Info = NewBlockChainTestInfo( + t, + types.NewArbitrumSigner(types.NewLondonSigner(builder.chainConfig.ChainID)), big.NewInt(l2pricing.InitialBaseFeeWei*2), + transferGas, + ) + + builder.nodeConfig.BatchPoster.MaxDelay = -1000 * time.Hour + cleanupA := builder.Build(t) + defer cleanupA() + + addNewBatchPoster(ctx, t, builder, srv.Address) + + builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ + builder.L1Info.PrepareTxTo("Faucet", &srv.Address, 30000, big.NewInt(1).Mul(big.NewInt(1e18), big.NewInt(1e18)), nil)}) + + l2nodeA := builder.L2.ConsensusNode + execNodeA := builder.L2.ExecNode + + config := arbnode.ConfigDefaultL1Test() + config.Sequencer = false + config.DelayedSequencer.Enable = false + config.BatchPoster.Enable = false + builder.execConfig.Sequencer.Enable = false + testClientB, cleanupB := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: config}) + defer cleanupB() + + l2nodeB := testClientB.ConsensusNode + execNodeB := testClientB.ExecNode + + nodeAGenesis := execNodeA.Backend.APIBackend().CurrentHeader().Hash() + nodeBGenesis := execNodeB.Backend.APIBackend().CurrentHeader().Hash() + if nodeAGenesis != nodeBGenesis { + Fatal(t, "node A L2 genesis hash", nodeAGenesis, "!= node B L2 genesis hash", nodeBGenesis) + } + + builder.BridgeBalance(t, "Faucet", big.NewInt(1).Mul(big.NewInt(params.Ether), big.NewInt(10000))) + + deployAuth := builder.L1Info.GetDefaultTransactOpts("RollupOwner", ctx) + + balance := big.NewInt(params.Ether) + balance.Mul(balance, big.NewInt(100)) + builder.L1Info.GenerateAccount("ValidatorA") + builder.L1.TransferBalance(t, "Faucet", "ValidatorA", balance, builder.L1Info) + l1authA := builder.L1Info.GetDefaultTransactOpts("ValidatorA", ctx) + + builder.L1Info.GenerateAccount("ValidatorB") + builder.L1.TransferBalance(t, "Faucet", "ValidatorB", balance, builder.L1Info) + l1authB := builder.L1Info.GetDefaultTransactOpts("ValidatorB", ctx) + + valWalletAddrAPtr, err := validatorwallet.GetValidatorWalletContract(ctx, l2nodeA.DeployInfo.ValidatorWalletCreator, 0, &l1authA, l2nodeA.L1Reader, true) + Require(t, err) + valWalletAddrA := *valWalletAddrAPtr + valWalletAddrCheck, err := validatorwallet.GetValidatorWalletContract(ctx, l2nodeA.DeployInfo.ValidatorWalletCreator, 0, &l1authA, l2nodeA.L1Reader, true) + Require(t, err) + if valWalletAddrA == *valWalletAddrCheck { + Require(t, err, "didn't cache validator wallet address", valWalletAddrA.String(), "vs", valWalletAddrCheck.String()) + } + + rollup, err := rollupgen.NewRollupAdminLogic(l2nodeA.DeployInfo.Rollup, builder.L1.Client) + Require(t, err) + + upgradeExecutor, err := upgrade_executorgen.NewUpgradeExecutor(l2nodeA.DeployInfo.UpgradeExecutor, builder.L1.Client) + Require(t, err, "unable to bind upgrade executor") + rollupABI, err := abi.JSON(strings.NewReader(rollupgen.RollupAdminLogicABI)) + Require(t, err, "unable to parse rollup ABI") + + safeAddress := deploySafe(t, builder.L1, builder.L1.Client, deployAuth, []common.Address{valWalletAddrA, srv.Address}) + setValidatorCalldata, err := rollupABI.Pack("setValidator", []common.Address{valWalletAddrA, l1authB.From, srv.Address, safeAddress}, []bool{true, true, true, true}) + Require(t, err, "unable to generate setValidator calldata") + tx, err := upgradeExecutor.ExecuteCall(&deployAuth, l2nodeA.DeployInfo.Rollup, setValidatorCalldata) + Require(t, err, "unable to set validators") + _, err = builder.L1.EnsureTxSucceeded(tx) + Require(t, err) + + setMinAssertPeriodCalldata, err := rollupABI.Pack("setMinimumAssertionPeriod", big.NewInt(1)) + Require(t, err, "unable to generate setMinimumAssertionPeriod calldata") + tx, err = upgradeExecutor.ExecuteCall(&deployAuth, l2nodeA.DeployInfo.Rollup, setMinAssertPeriodCalldata) + Require(t, err, "unable to set minimum assertion period") + _, err = builder.L1.EnsureTxSucceeded(tx) + Require(t, err) + + setAnyTrustFastConfirmerCalldata, err := rollupABI.Pack("setAnyTrustFastConfirmer", safeAddress) + Require(t, err, "unable to generate setAnyTrustFastConfirmer calldata") + tx, err = upgradeExecutor.ExecuteCall(&deployAuth, l2nodeA.DeployInfo.Rollup, setAnyTrustFastConfirmerCalldata) + Require(t, err, "unable to set anytrust fast confirmer") + _, err = builder.L1.EnsureTxSucceeded(tx) + Require(t, err) + + valConfig := staker.TestL1ValidatorConfig + valConfig.EnableFastConfirmation = true + valConfig.FastConfirmSafeAddress = safeAddress.String() + + parentChainID, err := builder.L1.Client.ChainID(ctx) + if err != nil { + t.Fatalf("Failed to get parent chain id: %v", err) + } + dpA, err := arbnode.StakerDataposter( + ctx, + rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), + l2nodeA.L1Reader, + &l1authA, NewFetcherFromConfig(arbnode.ConfigDefaultL1NonSequencerTest()), + nil, + parentChainID, + ) + if err != nil { + t.Fatalf("Error creating validator dataposter: %v", err) + } + valWalletA, err := validatorwallet.NewContract(dpA, nil, l2nodeA.DeployInfo.ValidatorWalletCreator, l2nodeA.DeployInfo.Rollup, l2nodeA.L1Reader, &l1authA, 0, func(common.Address) {}, func() uint64 { return valConfig.ExtraGas }) + Require(t, err) + valConfig.Strategy = "MakeNodes" + + _, valStack := createTestValidationNode(t, ctx, &valnode.TestValidationConfig) + blockValidatorConfig := staker.TestBlockValidatorConfig + + statelessA, err := staker.NewStatelessBlockValidator( + l2nodeA.InboxReader, + l2nodeA.InboxTracker, + l2nodeA.TxStreamer, + execNodeA, + l2nodeA.ArbDB, + nil, + StaticFetcherFrom(t, &blockValidatorConfig), + valStack, + ) + Require(t, err) + err = statelessA.Start(ctx) + Require(t, err) + stakerA, err := staker.NewStaker( + l2nodeA.L1Reader, + valWalletA, + bind.CallOpts{}, + valConfig, + nil, + statelessA, + nil, + nil, + l2nodeA.DeployInfo.ValidatorUtils, + nil, + ) + Require(t, err) + err = stakerA.Initialize(ctx) + Require(t, err) + err = valWalletA.Initialize(ctx) + Require(t, err) + cfg := arbnode.ConfigDefaultL1NonSequencerTest() + signerCfg, err := externalSignerTestCfg(srv.Address, srv.URL()) + if err != nil { + t.Fatalf("Error getting external signer config: %v", err) + } + cfg.Staker.DataPoster.ExternalSigner = *signerCfg + dpB, err := arbnode.StakerDataposter( + ctx, + rawdb.NewTable(l2nodeB.ArbDB, storage.StakerPrefix), + l2nodeB.L1Reader, + &l1authB, NewFetcherFromConfig(cfg), + nil, + parentChainID, + ) + if err != nil { + t.Fatalf("Error creating validator dataposter: %v", err) + } + valWalletB, err := validatorwallet.NewEOA(dpB, l2nodeB.DeployInfo.Rollup, l2nodeB.L1Reader.Client(), func() uint64 { return 0 }) + Require(t, err) + valConfig.Strategy = "watchtower" + statelessB, err := staker.NewStatelessBlockValidator( + l2nodeB.InboxReader, + l2nodeB.InboxTracker, + l2nodeB.TxStreamer, + execNodeB, + l2nodeB.ArbDB, + nil, + StaticFetcherFrom(t, &blockValidatorConfig), + valStack, + ) + Require(t, err) + err = statelessB.Start(ctx) + Require(t, err) + stakerB, err := staker.NewStaker( + l2nodeB.L1Reader, + valWalletB, + bind.CallOpts{}, + valConfig, + nil, + statelessB, + nil, + nil, + l2nodeB.DeployInfo.ValidatorUtils, + nil, + ) + Require(t, err) + err = stakerB.Initialize(ctx) + Require(t, err) + err = valWalletB.Initialize(ctx) + Require(t, err) + + builder.L2Info.GenerateAccount("BackgroundUser") + tx = builder.L2Info.PrepareTx("Faucet", "BackgroundUser", builder.L2Info.TransferGas, balance, nil) + err = builder.L2.Client.SendTransaction(ctx, tx) + Require(t, err) + _, err = builder.L2.EnsureTxSucceeded(tx) + Require(t, err) + + // Continually make L2 transactions in a background thread + backgroundTxsCtx, cancelBackgroundTxs := context.WithCancel(ctx) + backgroundTxsShutdownChan := make(chan struct{}) + defer (func() { + cancelBackgroundTxs() + <-backgroundTxsShutdownChan + })() + go (func() { + defer close(backgroundTxsShutdownChan) + err := makeBackgroundTxs(backgroundTxsCtx, builder) + if !errors.Is(err, context.Canceled) { + log.Warn("error making background txs", "err", err) + } + })() + + latestConfirmBeforeAct, err := rollup.LatestConfirmed(&bind.CallOpts{}) + Require(t, err) + tx, err = stakerA.Act(ctx) + Require(t, err) + if tx != nil { + _, err = builder.L1.EnsureTxSucceeded(tx) + Require(t, err) + } + latestConfirmAfterStakerAAct, err := rollup.LatestConfirmed(&bind.CallOpts{}) + Require(t, err) + if latestConfirmAfterStakerAAct != latestConfirmBeforeAct { + Fatal(t, "staker A alone advanced the latest confirmed node", latestConfirmAfterStakerAAct, "when it shouldn't have") + } + for j := 0; j < 5; j++ { + builder.L1.TransferBalance(t, "Faucet", "Faucet", common.Big0, builder.L1Info) + } + tx, err = stakerB.Act(ctx) + Require(t, err) + if tx != nil { + _, err = builder.L1.EnsureTxSucceeded(tx) + Require(t, err) + } + latestConfirmAfterStakerBAct, err := rollup.LatestConfirmed(&bind.CallOpts{}) + Require(t, err) + if latestConfirmAfterStakerBAct <= latestConfirmBeforeAct { + Fatal(t, "staker A and B together didn't advance the latest confirmed node") + } +} + +func deploySafe(t *testing.T, l1 *TestClient, backend bind.ContractBackend, deployAuth bind.TransactOpts, owners []common.Address) common.Address { + safeAddress, tx, _, err := contractsgen.DeploySafeL2(&deployAuth, backend) + Require(t, err) + _, err = l1.EnsureTxSucceeded(tx) + Require(t, err) + safeProxyAddress, tx, _, err := proxiesgen.DeploySafeProxy(&deployAuth, backend, safeAddress) + Require(t, err) + _, err = l1.EnsureTxSucceeded(tx) + Require(t, err) + var safe *contractsgen.Safe + safe, err = contractsgen.NewSafe(safeProxyAddress, backend) + Require(t, err) + _, err = l1.EnsureTxSucceeded(tx) + Require(t, err) + tx, err = safe.Setup( + &deployAuth, + owners, + big.NewInt(2), + common.Address{}, + nil, + common.Address{}, + common.Address{}, + big.NewInt(0), + common.Address{}, + ) + Require(t, err) + _, err = l1.EnsureTxSucceeded(tx) + Require(t, err) + return safeProxyAddress +} diff --git a/system_tests/fees_test.go b/system_tests/fees_test.go index 4d8fbf43fd..ccca82e009 100644 --- a/system_tests/fees_test.go +++ b/system_tests/fees_test.go @@ -2,8 +2,10 @@ // For license information, see https://github.com/nitro/blob/master/LICENSE // these tests seems to consume too much memory with race detection -//go:build !race -// +build !race +// Test randomly fails with L1 gas price estimate should tend toward the basefee +// so skipping locally, but running on CI +//go:build !race && cionly +// +build !race,cionly package arbtest diff --git a/system_tests/forwarder_test.go b/system_tests/forwarder_test.go index d29e82c12c..9fe419593e 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 @@ -200,7 +199,7 @@ func user(suffix string, idx int) string { } // tryWithTimeout calls function f() repeatedly foruntil it succeeds. -func tryWithTimeout(ctx context.Context, f func() error, duration time.Duration) error { +func tryWithTimeout(f func() error, duration time.Duration) error { for { select { case <-time.After(duration): @@ -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(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(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/full_challenge_mock_test.go b/system_tests/full_challenge_mock_test.go index 82f57dd7ad..b7f484210f 100644 --- a/system_tests/full_challenge_mock_test.go +++ b/system_tests/full_challenge_mock_test.go @@ -7,7 +7,6 @@ package arbtest import "testing" func TestMockChallengeManagerAsserterIncorrect(t *testing.T) { - t.Parallel() defaultWasmRootDir := "" for i := int64(1); i <= makeBatch_MsgsPerBatch*3; i++ { RunChallengeTest(t, false, true, i, defaultWasmRootDir) @@ -15,7 +14,6 @@ func TestMockChallengeManagerAsserterIncorrect(t *testing.T) { } func TestMockChallengeManagerAsserterCorrect(t *testing.T) { - t.Parallel() defaultWasmRootDir := "" for i := int64(1); i <= makeBatch_MsgsPerBatch*3; i++ { RunChallengeTest(t, true, true, i, defaultWasmRootDir) diff --git a/system_tests/meaningless_reorg_test.go b/system_tests/meaningless_reorg_test.go index 27ed8572c8..06a5d3d2b3 100644 --- a/system_tests/meaningless_reorg_test.go +++ b/system_tests/meaningless_reorg_test.go @@ -62,6 +62,8 @@ func TestMeaninglessBatchReorg(t *testing.T) { builder.L1.TransferBalance(t, "Faucet", "Faucet", common.Big1, builder.L1Info) } + compareAllMsgResultsFromConsensusAndExecution(t, builder.L2, "before reorg") + parentBlock := builder.L1.L1Backend.BlockChain().GetBlockByNumber(batchReceipt.BlockNumber.Uint64() - 1) err = builder.L1.L1Backend.BlockChain().ReorgToOldBlock(parentBlock) Require(t, err) @@ -104,4 +106,6 @@ func TestMeaninglessBatchReorg(t *testing.T) { if l2Header.Hash() != l2Receipt.BlockHash { Fatal(t, "L2 block hash changed") } + + compareAllMsgResultsFromConsensusAndExecution(t, builder.L2, "after reorg") } diff --git a/system_tests/program_recursive_test.go b/system_tests/program_recursive_test.go index 245d62fc0c..68d307948d 100644 --- a/system_tests/program_recursive_test.go +++ b/system_tests/program_recursive_test.go @@ -31,7 +31,7 @@ func testProgramRecursiveCall(t *testing.T, builder *NodeBuilder, slotVals map[s ctx := builder.ctx slot := common.HexToHash("0x11223344556677889900aabbccddeeff") val := common.Hash{} - args := []byte{} + var args []byte if recurse[0].opcode == vm.SSTORE { // send event from storage on sstore val = rander.GetHash() diff --git a/system_tests/program_test.go b/system_tests/program_test.go index b05589a1bf..5fa5db95c2 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" @@ -396,7 +397,6 @@ func storageTest(t *testing.T, jit bool) { } func TestProgramTransientStorage(t *testing.T) { - t.Parallel() transientStorageTest(t, true) } @@ -1474,6 +1474,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 @@ -1668,37 +1671,28 @@ func formatTime(duration time.Duration) string { return fmt.Sprintf("%.2f%s", span, units[unit]) } -func TestWasmRecreate(t *testing.T) { - builder, auth, cleanup := setupProgramTest(t, true) +func testWasmRecreate(t *testing.T, builder *NodeBuilder, storeTx *types.Transaction, loadTx *types.Transaction, want []byte) { ctx := builder.ctx l2info := builder.L2Info l2client := builder.L2.Client - defer cleanup() - - storage := deployWasm(t, ctx, auth, l2client, rustFile("storage")) - - zero := common.Hash{} - val := common.HexToHash("0x121233445566") // do an onchain call - store value - storeTx := l2info.PrepareTxTo("Owner", &storage, l2info.TransferGas, nil, argsForStorageWrite(zero, val)) Require(t, l2client.SendTransaction(ctx, storeTx)) _, err := EnsureTxSucceeded(ctx, l2client, storeTx) 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) Require(t, err) // make sure reading 2nd value succeeds from 2nd node - loadTx := l2info.PrepareTxTo("Owner", &storage, l2info.TransferGas, nil, argsForStorageRead(zero)) result, err := arbutil.SendTxAsCall(ctx, nodeB.Client, loadTx, l2info.GetAddress("Owner"), nil, true) Require(t, err) - if common.BytesToHash(result) != val { - Fatal(t, "got wrong value") + if !bytes.Equal(result, want) { + t.Fatalf("got wrong value, got %x, want %x", result, want) } // close nodeB cleanupB() @@ -1723,8 +1717,8 @@ func TestWasmRecreate(t *testing.T) { // test nodeB - answers eth_call (requires reloading wasm) result, err = arbutil.SendTxAsCall(ctx, nodeB.Client, loadTx, l2info.GetAddress("Owner"), nil, true) Require(t, err) - if common.BytesToHash(result) != val { - Fatal(t, "got wrong value") + if !bytes.Equal(result, want) { + t.Fatalf("got wrong value, got %x, want %x", result, want) } // send new tx (requires wasm) and check nodeB sees it as well @@ -1743,7 +1737,46 @@ func TestWasmRecreate(t *testing.T) { Fatal(t, "not contents found before delete") } os.RemoveAll(wasmPath) +} + +func TestWasmRecreate(t *testing.T) { + builder, auth, cleanup := setupProgramTest(t, true) + ctx := builder.ctx + l2info := builder.L2Info + l2client := builder.L2.Client + defer cleanup() + + storage := deployWasm(t, ctx, auth, l2client, rustFile("storage")) + + zero := common.Hash{} + val := common.HexToHash("0x121233445566") + + storeTx := l2info.PrepareTxTo("Owner", &storage, l2info.TransferGas, nil, argsForStorageWrite(zero, val)) + loadTx := l2info.PrepareTxTo("Owner", &storage, l2info.TransferGas, nil, argsForStorageRead(zero)) + + testWasmRecreate(t, builder, storeTx, loadTx, val[:]) +} + +func TestWasmRecreateWithDelegatecall(t *testing.T) { + builder, auth, cleanup := setupProgramTest(t, true) + ctx := builder.ctx + l2info := builder.L2Info + l2client := builder.L2.Client + defer cleanup() + + storage := deployWasm(t, ctx, auth, l2client, rustFile("storage")) + multicall := deployWasm(t, ctx, auth, l2client, rustFile("multicall")) + + zero := common.Hash{} + val := common.HexToHash("0x121233445566") + + data := argsForMulticall(vm.DELEGATECALL, storage, big.NewInt(0), argsForStorageWrite(zero, val)) + storeTx := l2info.PrepareTxTo("Owner", &multicall, l2info.TransferGas, nil, data) + + data = argsForMulticall(vm.DELEGATECALL, storage, big.NewInt(0), argsForStorageRead(zero)) + loadTx := l2info.PrepareTxTo("Owner", &multicall, l2info.TransferGas, nil, data) + testWasmRecreate(t, builder, storeTx, loadTx, val[:]) } // createMapFromDb is used in verifying if wasm store rebuilding works @@ -1786,7 +1819,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..09d53669ee 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 @@ -349,10 +361,8 @@ func testSkippingSavingStateAndRecreatingAfterRestart(t *testing.T, cacheConfig Require(t, err) l2info.GenerateAccount("User2") - var txs []*types.Transaction for i := genesis; i < uint64(txCount)+genesis; i++ { tx := l2info.PrepareTx("Owner", "User2", l2info.TransferGas, common.Big1, nil) - txs = append(txs, tx) err := client.SendTransaction(ctx, tx) Require(t, err) receipt, err := EnsureTxSucceeded(ctx, client, tx) @@ -427,8 +437,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 +480,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 +522,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 +572,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/reorg_resequencing_test.go b/system_tests/reorg_resequencing_test.go index b188504acb..70ab63bec1 100644 --- a/system_tests/reorg_resequencing_test.go +++ b/system_tests/reorg_resequencing_test.go @@ -1,6 +1,9 @@ // Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE +//go:build cionly +// +build cionly + package arbtest import ( @@ -15,6 +18,15 @@ import ( "github.com/offchainlabs/nitro/util/arbmath" ) +// This is a flaky test. +// During a reorg: +// 1. TransactionStreamer, holding insertionMutex lock, calls ExecutionEngine, which then adds old messages to a channel. +// After that, and before releasing the lock, TransactionStreamer does more computations. +// 2. Asynchronously, ExecutionEngine reads from this channel and calls TransactionStreamer, +// which expects that insertionMutex is free in order to succeed. +// +// If step 1 is still executing when Execution calls TransactionStreamer in step 2 then this error happens: +// 'failed to re-sequence old user message removed by reorg err="insert lock taken"' func TestReorgResequencing(t *testing.T) { t.Parallel() ctx, cancel := context.WithCancel(context.Background()) @@ -57,6 +69,7 @@ func TestReorgResequencing(t *testing.T) { Require(t, err) verifyBalances("after empty reorg") + compareAllMsgResultsFromConsensusAndExecution(t, builder.L2, "after empty reorg") prevMessage, err := builder.L2.ConsensusNode.TxStreamer.GetMessage(startMsgCount - 1) Require(t, err) @@ -82,7 +95,9 @@ func TestReorgResequencing(t *testing.T) { Require(t, err) accountsWithBalance = append(accountsWithBalance, "User4") + verifyBalances("after reorg with new deposit") + compareAllMsgResultsFromConsensusAndExecution(t, builder.L2, "after reorg with new deposit") err = builder.L2.ConsensusNode.TxStreamer.ReorgTo(startMsgCount) Require(t, err) @@ -91,4 +106,5 @@ func TestReorgResequencing(t *testing.T) { Require(t, err) verifyBalances("after second empty reorg") + compareAllMsgResultsFromConsensusAndExecution(t, builder.L2, "after second empty reorg") } diff --git a/system_tests/retryable_test.go b/system_tests/retryable_test.go index 268d59ac98..106dfc6d46 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" @@ -76,7 +75,7 @@ func retryableSetup(t *testing.T, modifyNodeConfig ...func(*NodeBuilder)) ( if !msgTypes[message.Message.Header.Kind] { continue } - txs, err := arbos.ParseL2Transactions(message.Message, params.ArbitrumDevTestChainConfig().ChainID, nil) + txs, err := arbos.ParseL2Transactions(message.Message, params.ArbitrumDevTestChainConfig().ChainID) Require(t, err) for _, tx := range txs { if txTypes[tx.Type()] { @@ -224,7 +223,7 @@ func TestSubmitRetryableImmediateSuccess(t *testing.T) { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, builder) + waitForL1DelayBlocks(t, builder) receipt, err := builder.L2.EnsureTxSucceeded(lookupL2Tx(l1Receipt)) Require(t, err) @@ -296,7 +295,7 @@ func testSubmitRetryableEmptyEscrow(t *testing.T, arbosVersion uint64) { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, builder) + waitForL1DelayBlocks(t, builder) l2Tx := lookupL2Tx(l1Receipt) receipt, err := builder.L2.EnsureTxSucceeded(l2Tx) @@ -363,7 +362,7 @@ func TestSubmitRetryableFailThenRetry(t *testing.T) { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, builder) + waitForL1DelayBlocks(t, builder) receipt, err := builder.L2.EnsureTxSucceeded(lookupL2Tx(l1Receipt)) Require(t, err) @@ -481,7 +480,7 @@ func TestSubmissionGasCosts(t *testing.T) { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, builder) + waitForL1DelayBlocks(t, builder) submissionTxOuter := lookupL2Tx(l1Receipt) submissionReceipt, err := builder.L2.EnsureTxSucceeded(submissionTxOuter) @@ -587,7 +586,7 @@ func TestSubmissionGasCosts(t *testing.T) { } } -func waitForL1DelayBlocks(t *testing.T, ctx context.Context, builder *NodeBuilder) { +func waitForL1DelayBlocks(t *testing.T, builder *NodeBuilder) { // sending l1 messages creates l1 blocks.. make enough to get that delayed inbox message in for i := 0; i < 30; i++ { builder.L1.SendWaitTestTransactions(t, []*types.Transaction{ @@ -623,7 +622,7 @@ func TestDepositETH(t *testing.T) { if l1Receipt.Status != types.ReceiptStatusSuccessful { t.Errorf("Got transaction status: %v, want: %v", l1Receipt.Status, types.ReceiptStatusSuccessful) } - waitForL1DelayBlocks(t, ctx, builder) + waitForL1DelayBlocks(t, builder) l2Receipt, err := builder.L2.EnsureTxSucceeded(lookupL2Tx(l1Receipt)) if err != nil { @@ -682,7 +681,7 @@ func TestArbitrumContractTx(t *testing.T) { if receipt.Status != types.ReceiptStatusSuccessful { t.Errorf("L1 transaction: %v has failed", l1tx.Hash()) } - waitForL1DelayBlocks(t, ctx, builder) + waitForL1DelayBlocks(t, builder) _, err = builder.L2.EnsureTxSucceeded(lookupL2Tx(receipt)) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", unsignedTx.Hash(), err) @@ -751,7 +750,7 @@ func TestL1FundedUnsignedTransaction(t *testing.T) { if receipt.Status != types.ReceiptStatusSuccessful { t.Errorf("L1 transaction: %v has failed", l1tx.Hash()) } - waitForL1DelayBlocks(t, ctx, builder) + waitForL1DelayBlocks(t, builder) receipt, err = builder.L2.EnsureTxSucceeded(unsignedTx) if err != nil { t.Fatalf("EnsureTxSucceeded(%v) unexpected error: %v", unsignedTx.Hash(), err) @@ -803,7 +802,7 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { Fatal(t, "l1Receipt indicated failure") } - waitForL1DelayBlocks(t, ctx, builder) + waitForL1DelayBlocks(t, builder) submissionTxOuter := lookupL2Tx(l1Receipt) submissionReceipt, err := builder.L2.EnsureTxSucceeded(submissionTxOuter) @@ -931,25 +930,128 @@ func TestRetryableSubmissionAndRedeemFees(t *testing.T) { } } +func TestRetryableRedeemBlockGasUsage(t *testing.T) { + builder, delayedInbox, lookupL2Tx, ctx, teardown := retryableSetup(t) + defer teardown() + l2client := builder.L2.Client + l2info := builder.L2Info + l1client := builder.L1.Client + l1info := builder.L1Info + + _, err := precompilesgen.NewArbosTest(common.HexToAddress("0x69"), l2client) + Require(t, err, "failed to deploy ArbosTest") + _, err = precompilesgen.NewArbRetryableTx(common.HexToAddress("6e"), l2client) + Require(t, err) + + ownerTxOpts := l2info.GetDefaultTransactOpts("Owner", ctx) + simpleAddr, _ := deploySimple(t, ctx, ownerTxOpts, l2client) + simpleABI, err := mocksgen.SimpleMetaData.GetAbi() + Require(t, err) + + beneficiaryAddress := l2info.GetAddress("Beneficiary") + deposit := arbmath.BigMul(big.NewInt(1e12), big.NewInt(1e12)) + callValue := common.Big0 + usertxoptsL1 := l1info.GetDefaultTransactOpts("Faucet", ctx) + usertxoptsL1.Value = deposit + l1tx, err := delayedInbox.CreateRetryableTicket( + &usertxoptsL1, + simpleAddr, + callValue, + big.NewInt(1e16), + beneficiaryAddress, + beneficiaryAddress, + // send enough L2 gas for intrinsic but not compute + big.NewInt(int64(params.TxGas+params.TxDataNonZeroGasEIP2028*4)), + big.NewInt(int64(l2pricing.InitialBaseFeeWei)*2), + simpleABI.Methods["incrementRedeem"].ID, + ) + Require(t, err) + l1Receipt, err := EnsureTxSucceeded(ctx, l1client, l1tx) + Require(t, err) + if l1Receipt.Status != types.ReceiptStatusSuccessful { + Fatal(t, "l1Receipt indicated failure") + } + waitForL1DelayBlocks(t, builder) + submissionReceipt, err := EnsureTxSucceeded(ctx, l2client, lookupL2Tx(l1Receipt)) + Require(t, err) + if len(submissionReceipt.Logs) != 2 { + Fatal(t, len(submissionReceipt.Logs)) + } + ticketId := submissionReceipt.Logs[0].Topics[1] + firstRetryTxId := submissionReceipt.Logs[1].Topics[2] + // get receipt for the auto redeem, make sure it failed + autoRedeemReceipt, err := WaitForTx(ctx, l2client, firstRetryTxId, time.Second*5) + Require(t, err) + if autoRedeemReceipt.Status != types.ReceiptStatusFailed { + Fatal(t, "first retry tx shouldn't have succeeded") + } + + redeemTx := func() *types.Transaction { + arbRetryableTxAbi, err := precompilesgen.ArbRetryableTxMetaData.GetAbi() + Require(t, err) + redeem := arbRetryableTxAbi.Methods["redeem"] + input, err := redeem.Inputs.Pack(ticketId) + Require(t, err) + data := append([]byte{}, redeem.ID...) + data = append(data, input...) + to := common.HexToAddress("6e") + gas := uint64(l2pricing.InitialPerBlockGasLimitV6) + return l2info.PrepareTxTo("Faucet", &to, gas, big.NewInt(0), data) + }() + burnTx := func() *types.Transaction { + burnAmount := uint64(20 * 1e6) + arbosTestAbi, err := precompilesgen.ArbosTestMetaData.GetAbi() + Require(t, err) + burnArbGas := arbosTestAbi.Methods["burnArbGas"] + input, err := burnArbGas.Inputs.Pack(arbmath.UintToBig(burnAmount - l2info.TransferGas)) + Require(t, err) + data := append([]byte{}, burnArbGas.ID...) + data = append(data, input...) + to := common.HexToAddress("0x69") + return l2info.PrepareTxTo("Faucet", &to, burnAmount, big.NewInt(0), data) + }() + receipts := SendSignedTxesInBatchViaL1(t, ctx, l1info, l1client, l2client, types.Transactions{redeemTx, burnTx}) + redeemReceipt, burnReceipt := receipts[0], receipts[1] + if len(redeemReceipt.Logs) != 1 { + Fatal(t, "Unexpected log count:", len(redeemReceipt.Logs)) + } + retryTxId := redeemReceipt.Logs[0].Topics[2] + + // check the receipt for the retry + retryReceipt, err := WaitForTx(ctx, l2client, retryTxId, time.Second*1) + Require(t, err) + if retryReceipt.Status != types.ReceiptStatusSuccessful { + Fatal(t, "retry failed") + } + t.Log("submission - block:", submissionReceipt.BlockNumber, "txInd:", submissionReceipt.TransactionIndex) + t.Log("auto redeem - block:", autoRedeemReceipt.BlockNumber, "txInd:", autoRedeemReceipt.TransactionIndex) + t.Log("redeem - block:", redeemReceipt.BlockNumber, "txInd:", redeemReceipt.TransactionIndex) + t.Log("retry - block:", retryReceipt.BlockNumber, "txInd:", retryReceipt.TransactionIndex) + t.Log("burn - block:", burnReceipt.BlockNumber, "txInd:", burnReceipt.TransactionIndex) + if !arbmath.BigEquals(burnReceipt.BlockNumber, redeemReceipt.BlockNumber) { + Fatal(t, "Failed to fit a tx to the same block as redeem and retry") + } +} + // elevateL2Basefee by burning gas exceeding speed limit func elevateL2Basefee(t *testing.T, ctx context.Context, builder *NodeBuilder) { baseFeeBefore := builder.L2.GetBaseFee(t) colors.PrintBlue("Elevating base fee...") - arbostestabi, err := precompilesgen.ArbosTestMetaData.GetAbi() + arbosTestAbi, err := precompilesgen.ArbosTestMetaData.GetAbi() Require(t, err) _, 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"] - data, err := burnArbGas.Inputs.Pack(arbmath.UintToBig(burnAmount - builder.L2Info.TransferGas)) + burnArbGas := arbosTestAbi.Methods["burnArbGas"] + input, err := burnArbGas.Inputs.Pack(arbmath.UintToBig(burnAmount - builder.L2Info.TransferGas)) Require(t, err) - input := append([]byte{}, burnArbGas.ID...) - input = append(input, data...) + data := append([]byte{}, burnArbGas.ID...) + data = append(data, input...) to := common.HexToAddress("0x69") - tx := builder.L2Info.PrepareTxTo("Faucet", &to, burnAmount, big.NewInt(0), input) + tx := builder.L2Info.PrepareTxTo("Faucet", &to, burnAmount, big.NewInt(0), data) Require(t, builder.L2.Client.SendTransaction(ctx, tx)) _, err = builder.L2.EnsureTxSucceeded(tx) Require(t, err) diff --git a/system_tests/seqfeed_test.go b/system_tests/seqfeed_test.go index e3a98b4961..5e70fdf098 100644 --- a/system_tests/seqfeed_test.go +++ b/system_tests/seqfeed_test.go @@ -8,6 +8,7 @@ import ( "fmt" "math/big" "net" + "reflect" "testing" "time" @@ -17,9 +18,11 @@ import ( "github.com/offchainlabs/nitro/arbnode" "github.com/offchainlabs/nitro/arbos/arbostypes" "github.com/offchainlabs/nitro/arbos/l1pricing" + "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/broadcastclient" "github.com/offchainlabs/nitro/broadcaster/backlog" "github.com/offchainlabs/nitro/broadcaster/message" + "github.com/offchainlabs/nitro/execution" "github.com/offchainlabs/nitro/execution/gethexec" "github.com/offchainlabs/nitro/relay" "github.com/offchainlabs/nitro/util/signature" @@ -144,8 +147,48 @@ func TestRelayedSequencerFeed(t *testing.T) { } } +func compareAllMsgResultsFromConsensusAndExecution( + t *testing.T, + testClient *TestClient, + testScenario string, +) *execution.MessageResult { + execHeadMsgNum, err := testClient.ExecNode.HeadMessageNumber() + Require(t, err) + consensusMsgCount, err := testClient.ConsensusNode.TxStreamer.GetMessageCount() + Require(t, err) + if consensusMsgCount != execHeadMsgNum+1 { + t.Fatal( + "consensusMsgCount", consensusMsgCount, "is different than (execHeadMsgNum + 1)", execHeadMsgNum, + "testScenario:", testScenario, + ) + } + + var lastResult *execution.MessageResult + for msgCount := 1; arbutil.MessageIndex(msgCount) <= consensusMsgCount; msgCount++ { + pos := msgCount - 1 + resultExec, err := testClient.ExecNode.ResultAtPos(arbutil.MessageIndex(pos)) + Require(t, err) + + resultConsensus, err := testClient.ConsensusNode.TxStreamer.ResultAtCount(arbutil.MessageIndex(msgCount)) + Require(t, err) + + if !reflect.DeepEqual(resultExec, resultConsensus) { + t.Fatal( + "resultExec", resultExec, "is different than resultConsensus", resultConsensus, + "pos:", pos, + "testScenario:", testScenario, + ) + } + + lastResult = resultExec + } + + return lastResult +} + func testLyingSequencer(t *testing.T, dasModeStr string) { t.Parallel() + ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -224,7 +267,9 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { t.Fatal("Unexpected balance:", l2balance) } - // Send the real transaction to client A + fraudResult := compareAllMsgResultsFromConsensusAndExecution(t, testClientB, "fraud") + + // Send the real transaction to client A, will cause a reorg on nodeB err = l2clientA.SendTransaction(ctx, realTx) if err != nil { t.Fatal("error sending real transaction:", err) @@ -255,6 +300,30 @@ func testLyingSequencer(t *testing.T, dasModeStr string) { if l2balanceRealAcct.Cmp(big.NewInt(1e12)) != 0 { t.Fatal("Unexpected balance of real account:", l2balanceRealAcct) } + + // Since NodeB is not a sequencer, it will produce blocks through Consensus. + // So it is expected that Consensus.ResultAtCount will not rely on Execution to retrieve results. + // However, since count 1 is related to genesis, and Execution is initialized through InitializeArbosInDatabase and not through Consensus, + // first call to Consensus.ResultAtCount with count equals to 1 will fall back to Execution. + // Not necessarily the first call to Consensus.ResultAtCount with count equals to 1 will happen through compareMsgResultFromConsensusAndExecution, + // so we don't test this here. + consensusMsgCount, err := testClientB.ConsensusNode.TxStreamer.GetMessageCount() + Require(t, err) + if consensusMsgCount != 2 { + t.Fatal("consensusMsgCount is different than 2") + } + logHandler := testhelpers.InitTestLog(t, log.LvlTrace) + _, err = testClientB.ConsensusNode.TxStreamer.ResultAtCount(arbutil.MessageIndex(2)) + Require(t, err) + if logHandler.WasLogged(arbnode.FailedToGetMsgResultFromDB) { + t.Fatal("Consensus relied on execution database to return the result") + } + // Consensus should update message result stored in its database after a reorg + realResult := compareAllMsgResultsFromConsensusAndExecution(t, testClientB, "real") + // Checks that results changed + if reflect.DeepEqual(fraudResult, realResult) { + t.Fatal("realResult and fraudResult are equal") + } } func TestLyingSequencer(t *testing.T) { @@ -333,7 +402,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) @@ -362,3 +431,62 @@ func TestBlockHashFeedMismatch(t *testing.T) { func TestBlockHashFeedNil(t *testing.T) { testBlockHashComparison(t, nil, false) } + +func TestPopulateFeedBacklog(t *testing.T) { + logHandler := testhelpers.InitTestLog(t, log.LvlTrace) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + builder := NewNodeBuilder(ctx).DefaultConfig(t, true) + builder.BuildL1(t) + + userAccount := "User2" + builder.L2Info.GenerateAccount(userAccount) + + // Guarantees that nodes will rely only on the feed to receive messages + builder.nodeConfig.BatchPoster.Enable = false + builder.BuildL2OnL1(t) + + dataDir := builder.l2StackConfig.DataDir + + // Sends a transaction + tx := builder.L2Info.PrepareTx("Owner", userAccount, builder.L2Info.TransferGas, big.NewInt(1e12), nil) + err := builder.L2.Client.SendTransaction(ctx, tx) + Require(t, err) + _, err = builder.L2.EnsureTxSucceeded(tx) + Require(t, err) + + // Shutdown node and starts a new one with same data dir and output feed enabled. + // The new node will populate the feedbacklog since already has a message, related to the + // transaction previously sent, stored in disk. + builder.L2.cleanup() + builder.l2StackConfig.DataDir = dataDir + builder.nodeConfig.Feed.Output = *newBroadcasterConfigTest() + cleanup := builder.BuildL2OnL1(t) + defer cleanup() + + // Creates a sink node that will read from the output feed of the previous node. + nodeConfigSink := builder.nodeConfig + port := builder.L2.ConsensusNode.BroadcastServer.ListenerAddr().(*net.TCPAddr).Port + nodeConfigSink.Feed.Input = *newBroadcastClientConfigTest(port) + testClientSink, cleanupSink := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: nodeConfigSink}) + defer cleanupSink() + + // Waits for the transaction to be processed by the sink node. + _, err = WaitForTx(ctx, testClientSink.Client, tx.Hash(), time.Second*5) + if err != nil { + t.Fatal("error waiting for transaction to get to sink:", err) + } + balance, err := testClientSink.Client.BalanceAt(ctx, builder.L2Info.GetAddress(userAccount), nil) + if err != nil { + t.Fatal("error getting fraud balance:", err) + } + if balance.Cmp(big.NewInt(1e12)) != 0 { + t.Fatal("Unexpected balance:", balance) + } + + if logHandler.WasLogged(arbnode.BlockHashMismatchLogMsg) { + t.Fatal("BlockHashMismatchLogMsg was logged unexpectedly") + } +} 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..24140e480d 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( @@ -56,8 +57,13 @@ func BuildBlock( batchFetcher := func(uint64) ([]byte, error) { return seqBatch, nil } + err = l1Message.FillInBatchGasCost(batchFetcher) + if err != nil { + return nil, err + } + block, _, err := arbos.ProduceBlock( - l1Message, delayedMessagesRead, lastBlockHeader, statedb, chainContext, chainConfig, batchFetcher, false, + l1Message, delayedMessagesRead, lastBlockHeader, statedb, chainContext, chainConfig, false, ) return block, err } @@ -137,8 +143,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 +156,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/test_info.go b/system_tests/test_info.go index a4fbb44c44..6313e392ca 100644 --- a/system_tests/test_info.go +++ b/system_tests/test_info.go @@ -16,7 +16,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" @@ -109,8 +108,8 @@ func (b *BlockchainTestInfo) GenerateGenesisAccount(name string, balance *big.In }) } -func (b *BlockchainTestInfo) GetGenesisAlloc() core.GenesisAlloc { - alloc := make(core.GenesisAlloc) +func (b *BlockchainTestInfo) GetGenesisAlloc() types.GenesisAlloc { + alloc := make(types.GenesisAlloc) for _, info := range b.ArbInitData.Accounts { var contractCode []byte contractStorage := make(map[common.Hash]common.Hash) @@ -120,7 +119,7 @@ func (b *BlockchainTestInfo) GetGenesisAlloc() core.GenesisAlloc { contractStorage[k] = v } } - alloc[info.Addr] = core.GenesisAccount{ + alloc[info.Addr] = types.Account{ Balance: new(big.Int).Set(info.EthBalance), Nonce: info.Nonce, Code: contractCode, diff --git a/system_tests/triedb_race_test.go b/system_tests/triedb_race_test.go index 9f14f08898..7828cf386d 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 @@ -72,7 +75,7 @@ func TestTrieDBCommitRace(t *testing.T) { for _, root := range roots { err := bc.TrieDB().Dereference(root) Require(t, err) - time.Sleep(1) + time.Sleep(time.Nanosecond) } } close(quit) diff --git a/system_tests/validation_mock_test.go b/system_tests/validation_mock_test.go index 1330f24882..2c6321d009 100644 --- a/system_tests/validation_mock_test.go +++ b/system_tests/validation_mock_test.go @@ -60,6 +60,10 @@ func (s *mockSpawner) WasmModuleRoots() ([]common.Hash, error) { return mockWasmModuleRoots, nil } +func (s *mockSpawner) StylusArchs() []string { + return []string{"mock"} +} + func (s *mockSpawner) Launch(entry *validator.ValidationInput, moduleRoot common.Hash) validator.ValidationRun { run := &mockValRun{ Promise: containers.NewPromise[validator.GoGlobalState](nil), diff --git a/util/arbmath/math.go b/util/arbmath/math.go index 7413955409..62af1e26e0 100644 --- a/util/arbmath/math.go +++ b/util/arbmath/math.go @@ -387,7 +387,7 @@ func DivCeil[T Unsigned](value, divisor T) T { // ApproxExpBasisPoints return the Maclaurin series approximation of e^x, where x is denominated in basis points. // The quartic polynomial will underestimate e^x by about 5% as x approaches 20000 bips. -func ApproxExpBasisPoints(value Bips, degree uint64) Bips { +func ApproxExpBasisPoints(value Bips, accuracy uint64) Bips { input := value negative := value < 0 if negative { @@ -396,9 +396,9 @@ func ApproxExpBasisPoints(value Bips, degree uint64) Bips { x := uint64(input) bips := uint64(OneInBips) - res := bips + x/degree - for i := uint64(1); i < degree; i++ { - res = bips + SaturatingUMul(res, x)/((degree-i)*bips) + res := bips + x/accuracy + for i := uint64(1); i < accuracy; i++ { + res = bips + SaturatingUMul(res, x)/((accuracy-i)*bips) } if negative { diff --git a/util/dbutil/dbutil.go b/util/dbutil/dbutil.go new file mode 100644 index 0000000000..a1eb6ce208 --- /dev/null +++ b/util/dbutil/dbutil.go @@ -0,0 +1,16 @@ +// Copyright 2021-2024, Offchain Labs, Inc. +// For license information, see https://github.com/nitro/blob/master/LICENSE + +package dbutil + +import ( + "errors" + + "github.com/cockroachdb/pebble" + "github.com/ethereum/go-ethereum/ethdb/memorydb" + "github.com/syndtr/goleveldb/leveldb" +) + +func IsErrNotFound(err error) bool { + return errors.Is(err, leveldb.ErrNotFound) || errors.Is(err, pebble.ErrNotFound) || errors.Is(err, memorydb.ErrMemorydbNotFound) +} diff --git a/util/headerreader/header_reader.go b/util/headerreader/header_reader.go index 06dfcfbfa8..074d24338e 100644 --- a/util/headerreader/header_reader.go +++ b/util/headerreader/header_reader.go @@ -63,6 +63,7 @@ type Config struct { Enable bool `koanf:"enable"` PollOnly bool `koanf:"poll-only" reload:"hot"` PollInterval time.Duration `koanf:"poll-interval" reload:"hot"` + PollTimeout time.Duration `koanf:"poll-timeout" reload:"hot"` SubscribeErrInterval time.Duration `koanf:"subscribe-err-interval" reload:"hot"` TxTimeout time.Duration `koanf:"tx-timeout" reload:"hot"` OldHeaderTimeout time.Duration `koanf:"old-header-timeout" reload:"hot"` @@ -80,6 +81,7 @@ var DefaultConfig = Config{ Enable: true, PollOnly: false, PollInterval: 15 * time.Second, + PollTimeout: 5 * time.Second, SubscribeErrInterval: 5 * time.Minute, TxTimeout: 5 * time.Minute, OldHeaderTimeout: 5 * time.Minute, @@ -94,6 +96,7 @@ func AddOptions(prefix string, f *flag.FlagSet) { f.Bool(prefix+".poll-only", DefaultConfig.PollOnly, "do not attempt to subscribe to header events") f.Bool(prefix+".use-finality-data", DefaultConfig.UseFinalityData, "use l1 data about finalized/safe blocks") f.Duration(prefix+".poll-interval", DefaultConfig.PollInterval, "interval when polling endpoint") + f.Duration(prefix+".poll-timeout", DefaultConfig.PollTimeout, "timeout when polling endpoint") f.Duration(prefix+".subscribe-err-interval", DefaultConfig.SubscribeErrInterval, "interval for subscribe error") f.Duration(prefix+".tx-timeout", DefaultConfig.TxTimeout, "timeout when waiting for a transaction") f.Duration(prefix+".old-header-timeout", DefaultConfig.OldHeaderTimeout, "warns if the latest l1 block is at least this old") @@ -108,6 +111,7 @@ var TestConfig = Config{ Enable: true, PollOnly: false, PollInterval: time.Millisecond * 10, + PollTimeout: time.Second * 5, TxTimeout: time.Second * 5, OldHeaderTimeout: 5 * time.Minute, UseFinalityData: false, @@ -287,7 +291,9 @@ func (s *HeaderReader) broadcastLoop(ctx context.Context) { s.possiblyBroadcast(h) timer.Stop() case <-timer.C: - h, err := s.client.HeaderByNumber(ctx, nil) + timedCtx, cancelFunc := context.WithTimeout(ctx, s.config().PollTimeout) + h, err := s.client.HeaderByNumber(timedCtx, nil) + cancelFunc() if err != nil { s.setError(fmt.Errorf("failed reading HeaderByNumber: %w", err)) if !errors.Is(err, context.Canceled) { diff --git a/util/rpcclient/rpcclient.go b/util/rpcclient/rpcclient.go index e171e6e99b..be5825a28d 100644 --- a/util/rpcclient/rpcclient.go +++ b/util/rpcclient/rpcclient.go @@ -44,6 +44,13 @@ func (c *ClientConfig) Validate() error { return err } +func (c *ClientConfig) UnmarshalJSON(data []byte) error { + // Use DefaultClientConfig for default values when unmarshalling JSON + *c = DefaultClientConfig + type clientConfigWithoutCustomUnmarshal ClientConfig + return json.Unmarshal(data, (*clientConfigWithoutCustomUnmarshal)(c)) +} + type ClientConfigFetcher func() *ClientConfig var TestClientConfig = ClientConfig{ diff --git a/util/rpcclient/rpcclient_test.go b/util/rpcclient/rpcclient_test.go index ae7e4fc226..1a7da54774 100644 --- a/util/rpcclient/rpcclient_test.go +++ b/util/rpcclient/rpcclient_test.go @@ -2,13 +2,17 @@ package rpcclient import ( "context" + "encoding/json" "errors" + "regexp" "sync/atomic" "testing" "time" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/rpc" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/offchainlabs/nitro/util/testhelpers" ) @@ -204,6 +208,21 @@ func TestIsAlreadyKnownError(t *testing.T) { } } +func TestUnmarshalClientConfig(t *testing.T) { + exampleJson := `[{"jwtsecret":"/tmp/nitro-val.jwt","url":"http://127.0.0.10:52000"}, {"jwtsecret":"/tmp/nitro-val.jwt","url":"http://127.0.0.10:52001"}]` + var clientConfigs []ClientConfig + Require(t, json.Unmarshal([]byte(exampleJson), &clientConfigs)) + expectedClientConfigs := []ClientConfig{DefaultClientConfig, DefaultClientConfig} + expectedClientConfigs[0].JWTSecret = "/tmp/nitro-val.jwt" + expectedClientConfigs[0].URL = "http://127.0.0.10:52000" + expectedClientConfigs[1].JWTSecret = "/tmp/nitro-val.jwt" + expectedClientConfigs[1].URL = "http://127.0.0.10:52001" + // Ensure the configs are equivalent to the expected configs, ignoring the retryErrors regexp as cmp can't compare it + if diff := cmp.Diff(expectedClientConfigs, clientConfigs, cmpopts.IgnoreTypes(®exp.Regexp{})); diff != "" { + t.Errorf("unmarshalling example JSON unexpected diff:\n%s", diff) + } +} + func Require(t *testing.T, err error, printables ...interface{}) { t.Helper() testhelpers.RequireImpl(t, err, printables...) 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..45ab653a1c --- /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 = "leveldb" + return &stackConf +} diff --git a/validator/client/redis/producer.go b/validator/client/redis/producer.go index 7594421f9a..b3ad0f8839 100644 --- a/validator/client/redis/producer.go +++ b/validator/client/redis/producer.go @@ -20,8 +20,10 @@ import ( type ValidationClientConfig struct { Name string `koanf:"name"` + StreamPrefix string `koanf:"stream-prefix"` Room int32 `koanf:"room"` RedisURL string `koanf:"redis-url"` + StylusArchs []string `koanf:"stylus-archs"` ProducerConfig pubsub.ProducerConfig `koanf:"producer-config"` CreateStreams bool `koanf:"create-streams"` } @@ -34,6 +36,7 @@ var DefaultValidationClientConfig = ValidationClientConfig{ Name: "redis validation client", Room: 2, RedisURL: "", + StylusArchs: []string{"wavm"}, ProducerConfig: pubsub.DefaultProducerConfig, CreateStreams: true, } @@ -42,6 +45,8 @@ var TestValidationClientConfig = ValidationClientConfig{ Name: "test redis validation client", Room: 2, RedisURL: "", + StreamPrefix: "test-", + StylusArchs: []string{"wavm"}, ProducerConfig: pubsub.TestProducerConfig, CreateStreams: false, } @@ -50,6 +55,8 @@ func ValidationClientConfigAddOptions(prefix string, f *pflag.FlagSet) { f.String(prefix+".name", DefaultValidationClientConfig.Name, "validation client name") f.Int32(prefix+".room", DefaultValidationClientConfig.Room, "validation client room") f.String(prefix+".redis-url", DefaultValidationClientConfig.RedisURL, "redis url") + f.String(prefix+".stream-prefix", DefaultValidationClientConfig.StreamPrefix, "prefix for stream name") + f.StringSlice(prefix+".stylus-archs", DefaultValidationClientConfig.StylusArchs, "archs required for stylus workers") pubsub.ProducerAddConfigAddOptions(prefix+".producer-config", f) f.Bool(prefix+".create-streams", DefaultValidationClientConfig.CreateStreams, "create redis streams if it does not exist") } @@ -57,14 +64,12 @@ func ValidationClientConfigAddOptions(prefix string, f *pflag.FlagSet) { // ValidationClient implements validation client through redis streams. type ValidationClient struct { stopwaiter.StopWaiter - name string - room atomic.Int32 + config *ValidationClientConfig + room atomic.Int32 // producers stores moduleRoot to producer mapping. - producers map[common.Hash]*pubsub.Producer[*validator.ValidationInput, validator.GoGlobalState] - producerConfig pubsub.ProducerConfig - redisClient redis.UniversalClient - moduleRoots []common.Hash - createStreams bool + producers map[common.Hash]*pubsub.Producer[*validator.ValidationInput, validator.GoGlobalState] + redisClient redis.UniversalClient + moduleRoots []common.Hash } func NewValidationClient(cfg *ValidationClientConfig) (*ValidationClient, error) { @@ -76,11 +81,9 @@ func NewValidationClient(cfg *ValidationClientConfig) (*ValidationClient, error) return nil, err } validationClient := &ValidationClient{ - name: cfg.Name, - producers: make(map[common.Hash]*pubsub.Producer[*validator.ValidationInput, validator.GoGlobalState]), - producerConfig: cfg.ProducerConfig, - redisClient: redisClient, - createStreams: cfg.CreateStreams, + config: cfg, + producers: make(map[common.Hash]*pubsub.Producer[*validator.ValidationInput, validator.GoGlobalState]), + redisClient: redisClient, } validationClient.room.Store(cfg.Room) return validationClient, nil @@ -88,8 +91,8 @@ func NewValidationClient(cfg *ValidationClientConfig) (*ValidationClient, error) func (c *ValidationClient) Initialize(ctx context.Context, moduleRoots []common.Hash) error { for _, mr := range moduleRoots { - if c.createStreams { - if err := pubsub.CreateStream(ctx, server_api.RedisStreamForRoot(mr), c.redisClient); err != nil { + if c.config.CreateStreams { + if err := pubsub.CreateStream(ctx, server_api.RedisStreamForRoot(c.config.StreamPrefix, mr), c.redisClient); err != nil { return fmt.Errorf("creating redis stream: %w", err) } } @@ -98,7 +101,7 @@ func (c *ValidationClient) Initialize(ctx context.Context, moduleRoots []common. continue } p, err := pubsub.NewProducer[*validator.ValidationInput, validator.GoGlobalState]( - c.redisClient, server_api.RedisStreamForRoot(mr), &c.producerConfig) + c.redisClient, server_api.RedisStreamForRoot(c.config.StreamPrefix, mr), &c.config.ProducerConfig) if err != nil { log.Warn("failed init redis for %v: %w", mr, err) continue @@ -146,10 +149,11 @@ func (c *ValidationClient) Stop() { } func (c *ValidationClient) Name() string { - if c.Started() { - return c.name - } - return "(not started)" + return c.config.Name +} + +func (c *ValidationClient) StylusArchs() []string { + return c.config.StylusArchs } func (c *ValidationClient) Room() int { diff --git a/validator/client/validation_client.go b/validator/client/validation_client.go index 79ecc6bdf4..d6743b109e 100644 --- a/validator/client/validation_client.go +++ b/validator/client/validation_client.go @@ -8,6 +8,7 @@ import ( "encoding/base64" "errors" "fmt" + "runtime" "sync/atomic" "time" @@ -29,13 +30,16 @@ type ValidationClient struct { stopwaiter.StopWaiter client *rpcclient.RpcClient name string + stylusArchs []string room atomic.Int32 wasmModuleRoots []common.Hash } func NewValidationClient(config rpcclient.ClientConfigFetcher, stack *node.Node) *ValidationClient { return &ValidationClient{ - client: rpcclient.NewRpcClient(config, stack), + client: rpcclient.NewRpcClient(config, stack), + name: "not started", + stylusArchs: []string{"not started"}, } } @@ -51,9 +55,7 @@ func (c *ValidationClient) Launch(entry *validator.ValidationInput, moduleRoot c return server_common.NewValRun(promise, moduleRoot) } -func (c *ValidationClient) Start(ctx_in context.Context) error { - c.StopWaiter.Start(ctx_in, c) - ctx := c.GetContext() +func (c *ValidationClient) Start(ctx context.Context) error { if err := c.client.Start(ctx); err != nil { return err } @@ -64,15 +66,27 @@ func (c *ValidationClient) Start(ctx_in context.Context) error { if len(name) == 0 { return errors.New("couldn't read name from server") } + var stylusArchs []string + if err := c.client.CallContext(ctx, &stylusArchs, server_api.Namespace+"_stylusArchs"); err != nil { + return err + } + if len(stylusArchs) == 0 { + return fmt.Errorf("could not read stylus archs from validation server") + } + for _, stylusArch := range stylusArchs { + if stylusArch != "wavm" && stylusArch != runtime.GOARCH && stylusArch != "mock" { + return fmt.Errorf("unsupported stylus architecture: %v", stylusArch) + } + } var moduleRoots []common.Hash - if err := c.client.CallContext(c.GetContext(), &moduleRoots, server_api.Namespace+"_wasmModuleRoots"); err != nil { + if err := c.client.CallContext(ctx, &moduleRoots, server_api.Namespace+"_wasmModuleRoots"); err != nil { return err } if len(moduleRoots) == 0 { return fmt.Errorf("server reported no wasmModuleRoots") } var room int - if err := c.client.CallContext(c.GetContext(), &room, server_api.Namespace+"_room"); err != nil { + if err := c.client.CallContext(ctx, &room, server_api.Namespace+"_room"); err != nil { return err } if room < 2 { @@ -84,6 +98,8 @@ func (c *ValidationClient) Start(ctx_in context.Context) error { c.room.Store(int32(room)) c.wasmModuleRoots = moduleRoots c.name = name + c.stylusArchs = stylusArchs + c.StopWaiter.Start(ctx, c) return nil } @@ -94,6 +110,13 @@ func (c *ValidationClient) WasmModuleRoots() ([]common.Hash, error) { return nil, errors.New("not started") } +func (c *ValidationClient) StylusArchs() []string { + if c.Started() { + return c.stylusArchs + } + return []string{"not started"} +} + func (c *ValidationClient) Stop() { c.StopWaiter.StopOnly() if c.client != nil { diff --git a/validator/interface.go b/validator/interface.go index 91668a3771..80aa2c1fcc 100644 --- a/validator/interface.go +++ b/validator/interface.go @@ -13,6 +13,7 @@ type ValidationSpawner interface { Start(context.Context) error Stop() Name() string + StylusArchs() []string Room() int } diff --git a/validator/server_api/json.go b/validator/server_api/json.go index 3dd817d5ae..90746e4c57 100644 --- a/validator/server_api/json.go +++ b/validator/server_api/json.go @@ -6,11 +6,12 @@ package server_api import ( "encoding/base64" "encoding/json" + "errors" "fmt" "os" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" + "github.com/offchainlabs/nitro/arbcompress" "github.com/offchainlabs/nitro/arbutil" "github.com/offchainlabs/nitro/util/jsonapi" @@ -45,8 +46,8 @@ func MachineStepResultFromJson(resultJson *MachineStepResultJson) (*validator.Ma }, nil } -func RedisStreamForRoot(moduleRoot common.Hash) string { - return fmt.Sprintf("stream:%s", moduleRoot.Hex()) +func RedisStreamForRoot(prefix string, moduleRoot common.Hash) string { + return fmt.Sprintf("%sstream:%s", prefix, moduleRoot.Hex()) } type Request struct { @@ -62,7 +63,7 @@ type InputJSON struct { BatchInfo []BatchInfoJson DelayedMsgB64 string StartState validator.GoGlobalState - UserWasms map[common.Hash]UserWasmJson + UserWasms map[string]map[common.Hash]string DebugChain bool } @@ -77,11 +78,6 @@ func (i *InputJSON) WriteToFile() error { return nil } -type UserWasmJson struct { - Module string - Asm string -} - type BatchInfoJson struct { Number uint64 DataB64 string @@ -99,19 +95,23 @@ func ValidationInputToJson(entry *validator.ValidationInput) *InputJSON { DelayedMsgB64: base64.StdEncoding.EncodeToString(entry.DelayedMsg), StartState: entry.StartState, PreimagesB64: jsonPreimagesMap, - UserWasms: make(map[common.Hash]UserWasmJson), + UserWasms: make(map[string]map[common.Hash]string), DebugChain: entry.DebugChain, } for _, binfo := range entry.BatchInfo { encData := base64.StdEncoding.EncodeToString(binfo.Data) res.BatchInfo = append(res.BatchInfo, BatchInfoJson{Number: binfo.Number, DataB64: encData}) } - for moduleHash, info := range entry.UserWasms { - encWasm := UserWasmJson{ - Asm: base64.StdEncoding.EncodeToString(info.Asm), - Module: base64.StdEncoding.EncodeToString(info.Module), + for arch, wasms := range entry.UserWasms { + archWasms := make(map[common.Hash]string) + for moduleHash, data := range wasms { + compressed, err := arbcompress.CompressLevel(data, 1) + if err != nil { + continue + } + archWasms[moduleHash] = base64.StdEncoding.EncodeToString(compressed) } - res.UserWasms[moduleHash] = encWasm + res.UserWasms[arch] = archWasms } return res } @@ -127,7 +127,7 @@ func ValidationInputFromJson(entry *InputJSON) (*validator.ValidationInput, erro DelayedMsgNr: entry.DelayedMsgNr, StartState: entry.StartState, Preimages: preimages, - UserWasms: make(state.UserWasms), + UserWasms: make(map[string]map[common.Hash][]byte), DebugChain: entry.DebugChain, } delayed, err := base64.StdEncoding.DecodeString(entry.DelayedMsgB64) @@ -146,20 +146,32 @@ func ValidationInputFromJson(entry *InputJSON) (*validator.ValidationInput, erro } valInput.BatchInfo = append(valInput.BatchInfo, decInfo) } - for moduleHash, info := range entry.UserWasms { - asm, err := base64.StdEncoding.DecodeString(info.Asm) - if err != nil { - return nil, err - } - module, err := base64.StdEncoding.DecodeString(info.Module) - if err != nil { - return nil, err - } - decInfo := state.ActivatedWasm{ - Asm: asm, - Module: module, + for arch, wasms := range entry.UserWasms { + archWasms := make(map[common.Hash][]byte) + for moduleHash, encoded := range wasms { + decoded, err := base64.StdEncoding.DecodeString(encoded) + if err != nil { + return nil, err + } + maxSize := 2_000_000 + var uncompressed []byte + for { + uncompressed, err = arbcompress.Decompress(decoded, maxSize) + if errors.Is(err, arbcompress.ErrOutputWontFit) { + if maxSize >= 512_000_000 { + return nil, errors.New("failed decompression: too large") + } + maxSize = maxSize * 4 + continue + } + if err != nil { + return nil, err + } + break + } + archWasms[moduleHash] = uncompressed } - valInput.UserWasms[moduleHash] = decInfo + valInput.UserWasms[arch] = archWasms } return valInput, nil } diff --git a/validator/server_arb/execution_run.go b/validator/server_arb/execution_run.go index 8bdce145a2..d29a88d34d 100644 --- a/validator/server_arb/execution_run.go +++ b/validator/server_arb/execution_run.go @@ -24,7 +24,7 @@ type executionRun struct { close sync.Once } -// NewExecutionChallengeBackend creates a backend with the given arguments. +// NewExecutionRun creates a backend with the given arguments. // Note: machineCache may be nil, but if present, it must not have a restricted range. func NewExecutionRun( ctxIn context.Context, diff --git a/validator/server_arb/validator_spawner.go b/validator/server_arb/validator_spawner.go index 7b9293f7bd..1d4126dc7c 100644 --- a/validator/server_arb/validator_spawner.go +++ b/validator/server_arb/validator_spawner.go @@ -88,6 +88,10 @@ func (s *ArbitratorSpawner) WasmModuleRoots() ([]common.Hash, error) { return s.locator.ModuleRoots(), nil } +func (s *ArbitratorSpawner) StylusArchs() []string { + return []string{"wavm"} +} + func (s *ArbitratorSpawner) Name() string { return "arbitrator" } @@ -118,8 +122,15 @@ func (v *ArbitratorSpawner) loadEntryToMachine(ctx context.Context, entry *valid return fmt.Errorf("error while trying to add sequencer msg for proving: %w", err) } } - for moduleHash, info := range entry.UserWasms { - err = mach.AddUserWasm(moduleHash, info.Module) + if len(entry.UserWasms["wavm"]) == 0 { + for stylusArch, wasms := range entry.UserWasms { + if len(wasms) > 0 { + return fmt.Errorf("bad stylus arch loaded to machine. Expected wavm. Got: %s", stylusArch) + } + } + } + for moduleHash, module := range entry.UserWasms["wavm"] { + err = mach.AddUserWasm(moduleHash, module) if err != nil { log.Error( "error adding user wasm for proving", diff --git a/validator/server_jit/jit_machine.go b/validator/server_jit/jit_machine.go index 1a3ccfa340..e4fb840cbb 100644 --- a/validator/server_jit/jit_machine.go +++ b/validator/server_jit/jit_machine.go @@ -12,6 +12,7 @@ import ( "net" "os" "os/exec" + "runtime" "time" "github.com/ethereum/go-ethereum/common" @@ -211,16 +212,25 @@ func (machine *JitMachine) prove( } } - // send user wasms - userWasms := entry.UserWasms + userWasms := entry.UserWasms[runtime.GOARCH] + + // if there are user wasms, but only for wrong architecture - error + if len(userWasms) == 0 { + for arch, userWasms := range entry.UserWasms { + if len(userWasms) != 0 { + return state, fmt.Errorf("bad stylus arch for validation input. got: %v, expected: %v", arch, runtime.GOARCH) + } + } + } + if err := writeUint32(uint32(len(userWasms))); err != nil { return state, err } - for moduleHash, info := range userWasms { + for moduleHash, program := range userWasms { if err := writeExact(moduleHash[:]); err != nil { return state, err } - if err := writeBytes(info.Asm); err != nil { + if err := writeBytes(program); err != nil { return state, err } } diff --git a/validator/server_jit/spawner.go b/validator/server_jit/spawner.go index eda74b2911..5ba3664109 100644 --- a/validator/server_jit/spawner.go +++ b/validator/server_jit/spawner.go @@ -71,6 +71,10 @@ func (v *JitSpawner) WasmModuleRoots() ([]common.Hash, error) { return v.locator.ModuleRoots(), nil } +func (v *JitSpawner) StylusArchs() []string { + return []string{runtime.GOARCH} +} + func (v *JitSpawner) execute( ctx context.Context, entry *validator.ValidationInput, moduleRoot common.Hash, ) (validator.GoGlobalState, error) { diff --git a/validator/validation_entry.go b/validator/validation_entry.go index 446f84ca62..133a67a8a8 100644 --- a/validator/validation_entry.go +++ b/validator/validation_entry.go @@ -2,7 +2,6 @@ package validator import ( "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/state" "github.com/offchainlabs/nitro/arbutil" ) @@ -17,7 +16,7 @@ type ValidationInput struct { HasDelayedMsg bool DelayedMsgNr uint64 Preimages map[arbutil.PreimageType]map[common.Hash][]byte - UserWasms state.UserWasms + UserWasms map[string]map[common.Hash][]byte BatchInfo []BatchInfo DelayedMsg []byte StartState GoGlobalState diff --git a/validator/valnode/redis/consumer.go b/validator/valnode/redis/consumer.go index 84f597c095..fb7db1e870 100644 --- a/validator/valnode/redis/consumer.go +++ b/validator/valnode/redis/consumer.go @@ -37,7 +37,7 @@ func NewValidationServer(cfg *ValidationServerConfig, spawner validator.Validati consumers := make(map[common.Hash]*pubsub.Consumer[*validator.ValidationInput, validator.GoGlobalState]) for _, hash := range cfg.ModuleRoots { mr := common.HexToHash(hash) - c, err := pubsub.NewConsumer[*validator.ValidationInput, validator.GoGlobalState](redisClient, server_api.RedisStreamForRoot(mr), &cfg.ConsumerConfig) + c, err := pubsub.NewConsumer[*validator.ValidationInput, validator.GoGlobalState](redisClient, server_api.RedisStreamForRoot(cfg.StreamPrefix, mr), &cfg.ConsumerConfig) if err != nil { return nil, fmt.Errorf("creating consumer for validation: %w", err) } @@ -130,10 +130,12 @@ type ValidationServerConfig struct { ModuleRoots []string `koanf:"module-roots"` // Timeout on polling for existence of each redis stream. StreamTimeout time.Duration `koanf:"stream-timeout"` + StreamPrefix string `koanf:"stream-prefix"` } var DefaultValidationServerConfig = ValidationServerConfig{ RedisURL: "", + StreamPrefix: "", ConsumerConfig: pubsub.DefaultConsumerConfig, ModuleRoots: []string{}, StreamTimeout: 10 * time.Minute, @@ -141,6 +143,7 @@ var DefaultValidationServerConfig = ValidationServerConfig{ var TestValidationServerConfig = ValidationServerConfig{ RedisURL: "", + StreamPrefix: "test-", ConsumerConfig: pubsub.TestConsumerConfig, ModuleRoots: []string{}, StreamTimeout: time.Minute, @@ -150,6 +153,7 @@ func ValidationServerConfigAddOptions(prefix string, f *pflag.FlagSet) { pubsub.ConsumerConfigAddOptions(prefix+".consumer-config", f) f.StringSlice(prefix+".module-roots", nil, "Supported module root hashes") f.String(prefix+".redis-url", DefaultValidationServerConfig.RedisURL, "url of redis server") + f.String(prefix+".stream-prefix", DefaultValidationServerConfig.StreamPrefix, "prefix for stream name") f.Duration(prefix+".stream-timeout", DefaultValidationServerConfig.StreamTimeout, "Timeout on polling for existence of redis streams") } diff --git a/validator/valnode/validation_api.go b/validator/valnode/validation_api.go index 3299366821..6245ffc5e3 100644 --- a/validator/valnode/validation_api.go +++ b/validator/valnode/validation_api.go @@ -44,6 +44,10 @@ func (a *ValidationServerAPI) WasmModuleRoots() ([]common.Hash, error) { return a.spawner.WasmModuleRoots() } +func (a *ValidationServerAPI) StylusArchs() ([]string, error) { + return a.spawner.StylusArchs(), nil +} + func NewValidationServerAPI(spawner validator.ValidationSpawner) *ValidationServerAPI { return &ValidationServerAPI{spawner} } diff --git a/wsbroadcastserver/clientconnection.go b/wsbroadcastserver/clientconnection.go index 7fb88bf9eb..16a8f64daf 100644 --- a/wsbroadcastserver/clientconnection.go +++ b/wsbroadcastserver/clientconnection.go @@ -193,6 +193,7 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { t := time.NewTimer(cc.delay) select { case <-ctx.Done(): + t.Stop() return case <-t.C: } @@ -222,8 +223,10 @@ func (cc *ClientConnection) Start(parentCtx context.Context) { timer := time.NewTimer(5 * time.Second) select { case <-ctx.Done(): + timer.Stop() return case <-cc.registered: + timer.Stop() log.Debug("ClientConnection registered with ClientManager", "client", cc.Name) case <-timer.C: log.Error("timed out waiting for ClientConnection to register with ClientManager", "client", cc.Name)