diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 0203a4654a0..1ba584e8db8 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -18,22 +18,27 @@ jobs: runs-on: group: Reth steps: - - uses: actions/checkout@v5 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: submodules: true - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - name: Install cargo-codspeed - uses: taiki-e/install-action@v2 + uses: taiki-e/install-action@a37010ded18ff788be4440302bd6830b1ae50d8b # v2.68.25 with: tool: cargo-codspeed - name: Build the benchmark target(s) run: ./.github/scripts/codspeed-build.sh - name: Run the benchmarks - uses: CodSpeedHQ/action@v4 + uses: CodSpeedHQ/action@281164b0f014a4e7badd2c02cecad9b595b70537 # v4.11.1 with: run: cargo codspeed run --workspace mode: instrumentation diff --git a/.github/workflows/book.yml b/.github/workflows/book.yml index c4262cbb3ad..2cf26c9375b 100644 --- a/.github/workflows/book.yml +++ b/.github/workflows/book.yml @@ -15,11 +15,16 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 90 steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - name: Install bun - uses: oven-sh/setup-bun@v2 + uses: oven-sh/setup-bun@ecf28ddc73e819eb6fa29df6b34ef8921c743461 # v2.1.3 with: bun-version: v1.2.23 @@ -31,7 +36,7 @@ jobs: npx playwright install --with-deps chromium - name: Install Rust nightly - uses: dtolnay/rust-toolchain@nightly + uses: dtolnay/rust-toolchain@0f1b44df7e9cbb178d781a242338dfa5e243ad7f # nightly - name: Build docs run: cd docs/vocs && bash scripts/build-cargo-docs.sh @@ -42,10 +47,10 @@ jobs: echo "Vocs Build Complete" - name: Setup Pages - uses: actions/configure-pages@v5 + uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 - name: Upload artifact - uses: actions/upload-pages-artifact@v4 + uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0 with: path: "./docs/vocs/docs/dist" @@ -67,6 +72,11 @@ jobs: timeout-minutes: 60 steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 diff --git a/.github/workflows/compact.yml b/.github/workflows/compact.yml index 8a18df872d2..f6a1e5f594b 100644 --- a/.github/workflows/compact.yml +++ b/.github/workflows/compact.yml @@ -25,13 +25,18 @@ jobs: - cargo run --bin reth --features "dev" - cargo run --bin op-reth --features "dev" --manifest-path crates/optimism/bin/Cargo.toml steps: - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - name: Checkout base - uses: actions/checkout@v5 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: ref: ${{ github.base_ref || 'main' }} # On `main` branch, generates test vectors and serializes them to disk using `Compact`. @@ -39,7 +44,7 @@ jobs: run: | ${{ matrix.bin }} -- test-vectors compact --write - name: Checkout PR - uses: actions/checkout@v5 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: clean: false # On incoming merge try to read and decode previously generated vectors with `Compact` diff --git a/.github/workflows/docker-git.yml b/.github/workflows/docker-git.yml index 62830608d67..3cdacfd973f 100644 --- a/.github/workflows/docker-git.yml +++ b/.github/workflows/docker-git.yml @@ -17,6 +17,9 @@ env: DOCKER_USERNAME: ${{ github.actor }} GIT_SHA: ${{ github.sha }} +permissions: + contents: read + jobs: build: name: build and push @@ -33,10 +36,15 @@ jobs: - name: 'Build and push the git-sha-tagged op-reth image' command: 'make IMAGE_NAME=$OP_IMAGE_NAME DOCKER_IMAGE_NAME=$OP_DOCKER_IMAGE_NAME GIT_SHA=$GIT_SHA PROFILE=maxperf op-docker-build-push-git-sha' steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - name: Install cross main diff --git a/.github/workflows/docker-nightly.yml b/.github/workflows/docker-nightly.yml index 213b2314060..db3bb0e688f 100644 --- a/.github/workflows/docker-nightly.yml +++ b/.github/workflows/docker-nightly.yml @@ -15,6 +15,9 @@ env: OP_DOCKER_IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/op-reth DOCKER_USERNAME: ${{ github.actor }} +permissions: + contents: read + jobs: build: name: build and push @@ -35,15 +38,20 @@ jobs: - name: 'Build and push the nightly profiling op-reth image' command: 'make IMAGE_NAME=$OP_IMAGE_NAME DOCKER_IMAGE_NAME=$OP_DOCKER_IMAGE_NAME PROFILE=profiling op-docker-build-push-nightly-profiling' steps: - - uses: actions/checkout@v5 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - name: Remove bloatware - uses: laverdet/remove-bloatware@v1.0.0 + uses: laverdet/remove-bloatware@a027d55a72759ee60f8e538ffd01f114e982fd57 # v1.0.0 with: docker: true lang: rust - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - name: Install cross main diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 0768ea8e79a..86fb3e68dff 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -15,6 +15,9 @@ env: OP_DOCKER_IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/op-reth DOCKER_USERNAME: ${{ github.actor }} +permissions: + contents: read + jobs: build-rc: if: contains(github.ref, '-rc') @@ -32,10 +35,15 @@ jobs: - name: "Build and push op-reth image" command: "make IMAGE_NAME=$OP_IMAGE_NAME DOCKER_IMAGE_NAME=$OP_DOCKER_IMAGE_NAME PROFILE=maxperf op-docker-build-push" steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - name: Install cross main @@ -68,10 +76,15 @@ jobs: - name: "Build and push op-reth image" command: "make IMAGE_NAME=$OP_IMAGE_NAME DOCKER_IMAGE_NAME=$OP_DOCKER_IMAGE_NAME PROFILE=maxperf op-docker-build-push-latest" steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - name: Install cross main diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 16c9fb2f613..9bde30a643c 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -25,10 +25,15 @@ jobs: RUST_BACKTRACE: 1 timeout-minutes: 90 steps: - - uses: actions/checkout@v5 - - uses: dtolnay/rust-toolchain@stable - - uses: taiki-e/install-action@nextest - - uses: Swatinem/rust-cache@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + - uses: taiki-e/install-action@65695e4d3f689d823ed155c836d20e98522ad93f # nextest + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - name: Run e2e tests diff --git a/.github/workflows/hive.yml b/.github/workflows/hive.yml index 7d0ac65bee7..00566a08ac3 100644 --- a/.github/workflows/hive.yml +++ b/.github/workflows/hive.yml @@ -27,9 +27,14 @@ jobs: runs-on: group: Reth steps: - - uses: actions/checkout@v5 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - name: Checkout hive tests - uses: actions/checkout@v5 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: repository: ethereum/hive path: hivetests @@ -38,14 +43,14 @@ jobs: id: hive-commit run: echo "hash=$(cd hivetests && git rev-parse HEAD)" >> $GITHUB_OUTPUT - - uses: actions/setup-go@v6 + - uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0 with: go-version: "^1.13.1" - run: go version - name: Restore hive assets cache id: cache-hive - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ./hive_assets key: hive-assets-${{ steps.hive-commit.outputs.hash }}-${{ hashFiles('.github/assets/hive/build_simulators.sh') }} @@ -68,7 +73,7 @@ jobs: chmod +x hive - name: Upload hive assets - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: hive_assets path: ./hive_assets @@ -184,18 +189,23 @@ jobs: permissions: issues: write steps: - - uses: actions/checkout@v5 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: fetch-depth: 0 - name: Download hive assets - uses: actions/download-artifact@v6 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: hive_assets path: /tmp - name: Download reth image - uses: actions/download-artifact@v6 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: artifacts path: /tmp @@ -209,7 +219,7 @@ jobs: chmod +x /usr/local/bin/hive - name: Checkout hive tests - uses: actions/checkout@v5 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: repository: ethereum/hive ref: master @@ -250,8 +260,13 @@ jobs: runs-on: group: Reth steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + - name: Slack Webhook Action - uses: rtCamp/action-slack-notify@v2 + uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3 env: SLACK_COLOR: ${{ job.status }} SLACK_MESSAGE: "Failed run: https://github.com/paradigmxyz/reth/actions/runs/${{ github.run_id }}" diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 90e3287917e..b3c5ff6ac2c 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -32,13 +32,18 @@ jobs: network: ["ethereum", "optimism"] timeout-minutes: 60 steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable - name: Install Geth run: .github/assets/install_geth.sh - - uses: taiki-e/install-action@nextest - - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@65695e4d3f689d823ed155c836d20e98522ad93f # nextest + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - if: matrix.network == 'ethereum' @@ -61,8 +66,13 @@ jobs: needs: [test] timeout-minutes: 30 steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + - name: Decide whether the needed jobs succeeded or failed - uses: re-actors/alls-green@release/v1 + uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # release/v1 with: jobs: ${{ toJSON(needs) }} @@ -71,11 +81,16 @@ jobs: if: github.event_name == 'schedule' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable - - uses: taiki-e/install-action@nextest - - uses: Swatinem/rust-cache@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + - uses: taiki-e/install-action@65695e4d3f689d823ed155c836d20e98522ad93f # nextest + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - name: run era1 files integration tests diff --git a/.github/workflows/kurtosis-op.yml b/.github/workflows/kurtosis-op.yml index 7477e759209..a8ee26d475b 100644 --- a/.github/workflows/kurtosis-op.yml +++ b/.github/workflows/kurtosis-op.yml @@ -37,12 +37,17 @@ jobs: needs: - prepare-reth steps: - - uses: actions/checkout@v5 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: fetch-depth: 0 - name: Download reth image - uses: actions/download-artifact@v6 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: artifacts path: /tmp @@ -54,7 +59,7 @@ jobs: docker image ls -a - name: Install Foundry - uses: foundry-rs/foundry-toolchain@v1 + uses: foundry-rs/foundry-toolchain@8789b3e21e6c11b2697f5eb56eddae542f746c10 # v1.7.0 - name: Run kurtosis run: | @@ -90,8 +95,13 @@ jobs: runs-on: group: Reth steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + - name: Slack Webhook Action - uses: rtCamp/action-slack-notify@v2 + uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3 env: SLACK_COLOR: ${{ job.status }} SLACK_MESSAGE: "Failed run: https://github.com/paradigmxyz/reth/actions/runs/${{ github.run_id }}" diff --git a/.github/workflows/kurtosis.yml b/.github/workflows/kurtosis.yml index b45e997ef73..6632c69d11e 100644 --- a/.github/workflows/kurtosis.yml +++ b/.github/workflows/kurtosis.yml @@ -35,12 +35,17 @@ jobs: needs: - prepare-reth steps: - - uses: actions/checkout@v5 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: fetch-depth: 0 - name: Download reth image - uses: actions/download-artifact@v6 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: artifacts path: /tmp @@ -52,7 +57,7 @@ jobs: docker image ls -a - name: Run kurtosis - uses: ethpandaops/kurtosis-assertoor-github-action@v1 + uses: ethpandaops/kurtosis-assertoor-github-action@5932604b244dbd2ddb811516b516a9094f4d2c2f # v1 with: ethereum_package_args: '.github/assets/kurtosis_network_params.yaml' @@ -62,8 +67,13 @@ jobs: runs-on: group: Reth steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + - name: Slack Webhook Action - uses: rtCamp/action-slack-notify@v2 + uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3 env: SLACK_COLOR: ${{ job.status }} SLACK_MESSAGE: "Failed run: https://github.com/paradigmxyz/reth/actions/runs/${{ github.run_id }}" diff --git a/.github/workflows/label-pr.yml b/.github/workflows/label-pr.yml index d4b4bf07cc4..28ca294ee33 100644 --- a/.github/workflows/label-pr.yml +++ b/.github/workflows/label-pr.yml @@ -4,6 +4,9 @@ on: pull_request: types: [opened] +permissions: + contents: read + jobs: label_prs: runs-on: ubuntu-latest @@ -11,12 +14,17 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/checkout@v5 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: fetch-depth: 0 - name: Label PRs - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: | const label_pr = require('./.github/assets/label_pr.js') diff --git a/.github/workflows/lint-actions.yml b/.github/workflows/lint-actions.yml index f408c4f50a5..7441f194a88 100644 --- a/.github/workflows/lint-actions.yml +++ b/.github/workflows/lint-actions.yml @@ -8,11 +8,19 @@ on: paths: - '.github/**' +permissions: + contents: read + jobs: actionlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - name: Download actionlint id: get_actionlint run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 309a25218b7..1083629c47e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -21,16 +21,21 @@ jobs: args: --workspace --lib --examples --tests --benches --locked features: "ethereum asm-keccak jemalloc jemalloc-prof min-error-logs min-warn-logs min-info-logs min-debug-logs min-trace-logs" steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@clippy + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@1d1f857d532eed3727f0993694a0c626df9cb0fb # clippy with: components: clippy - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - if: "${{ matrix.type == 'book' }}" - uses: arduino/setup-protoc@v3 + uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Run clippy on binaries @@ -43,12 +48,17 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@nightly + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@0f1b44df7e9cbb178d781a242338dfa5e243ad7f # nightly with: components: clippy - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - run: cargo clippy --workspace --lib --examples --tests --benches --all-features --locked @@ -59,16 +69,21 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable with: target: wasm32-wasip1 - - uses: taiki-e/install-action@cargo-hack - - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@c204cf7dec81b48d318110287b0eefd4b7903c5f # cargo-hack + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - - uses: dcarbone/install-jq-action@v3 + - uses: dcarbone/install-jq-action@b7ef57d46ece78760b4019dbc4080a1ba2a40b45 # v3.2.0 - name: Run Wasm checks run: | sudo apt update && sudo apt install gcc-multilib @@ -78,16 +93,21 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable with: target: riscv32imac-unknown-none-elf - - uses: taiki-e/install-action@cargo-hack - - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@c204cf7dec81b48d318110287b0eefd4b7903c5f # cargo-hack + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - - uses: dcarbone/install-jq-action@v3 + - uses: dcarbone/install-jq-action@b7ef57d46ece78760b4019dbc4080a1ba2a40b45 # v3.2.0 - name: Run RISC-V checks run: .github/assets/check_rv32imac.sh @@ -95,11 +115,16 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable - - uses: taiki-e/install-action@cargo-hack - - uses: Swatinem/rust-cache@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + - uses: taiki-e/install-action@c204cf7dec81b48d318110287b0eefd4b7903c5f # cargo-hack + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - run: cargo hack check --workspace @@ -114,12 +139,17 @@ jobs: - binary: reth - binary: op-reth steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@master + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@efa25f7f19611383d5b0ccf2d1c8914531636bf9 # master with: toolchain: "1.88" # MSRV - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - run: cargo build --bin "${{ matrix.binary }}" --workspace @@ -131,10 +161,15 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@nightly - - uses: Swatinem/rust-cache@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@0f1b44df7e9cbb178d781a242338dfa5e243ad7f # nightly + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - run: cargo docs --document-private-items @@ -148,9 +183,14 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@nightly + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@0f1b44df7e9cbb178d781a242338dfa5e243ad7f # nightly with: components: rustfmt - name: Run fmt @@ -161,13 +201,18 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@nightly - - uses: Swatinem/rust-cache@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@0f1b44df7e9cbb178d781a242338dfa5e243ad7f # nightly + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - - uses: taiki-e/install-action@cargo-udeps + - uses: taiki-e/install-action@31c73f16da4675f7c2082206ef46202e0a85f120 # cargo-udeps - run: cargo udeps --workspace --lib --examples --tests --benches --all-features --locked book: @@ -175,10 +220,15 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@nightly - - uses: Swatinem/rust-cache@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@0f1b44df7e9cbb178d781a242338dfa5e243ad7f # nightly + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - run: cargo build --bin reth --workspace --features ethereum @@ -192,17 +242,27 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v5 - - uses: crate-ci/typos@v1 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: crate-ci/typos@631208b7aac2daa8b707f55e7331f9112b0e062d # v1.44.0 check-toml: runs-on: ubuntu-latest timeout-minutes: 30 steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - name: Run dprint - uses: dprint/check@v2.3 + uses: dprint/check@9cb3a2b17a8e606d37aae341e49df3654933fc23 # v2.3 with: config-path: dprint.json @@ -210,9 +270,14 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v5 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - name: Check dashboard JSON with jq - uses: sergeysova/jq-action@v2 + uses: sergeysova/jq-action@a3f0d4ff59cc1dddf023fc0b325dd75b10deec58 # v2.3.0 with: cmd: jq empty etc/grafana/dashboards/overview.json @@ -220,9 +285,14 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable - name: Ensure no arbitrary or proptest dependency on default build run: cargo tree --package reth -e=features,no-dev | grep -Eq "arbitrary|proptest" && exit 1 || exit 0 @@ -232,14 +302,19 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@clippy - - uses: Swatinem/rust-cache@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@1d1f857d532eed3727f0993694a0c626df9cb0fb # clippy + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - name: cargo install cargo-hack - uses: taiki-e/install-action@cargo-hack + uses: taiki-e/install-action@c204cf7dec81b48d318110287b0eefd4b7903c5f # cargo-hack - run: make check-features env: RUSTFLAGS: -D warnings @@ -249,10 +324,15 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 20 steps: - - uses: actions/checkout@v5 - - uses: dtolnay/rust-toolchain@stable - - uses: rui314/setup-mold@v1 - - uses: taiki-e/cache-cargo-install-action@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: taiki-e/cache-cargo-install-action@7447f04c51f2ba27ca35e7f1e28fab848c5b3ba7 # v2.3.1 with: tool: zepter - name: Eagerly pull dependencies @@ -283,7 +363,12 @@ jobs: - deny timeout-minutes: 30 steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + - name: Decide whether the needed jobs succeeded or failed - uses: re-actors/alls-green@release/v1 + uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # release/v1 with: jobs: ${{ toJSON(needs) }} diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml index e30045423bd..6fb86019543 100644 --- a/.github/workflows/pr-title.yml +++ b/.github/workflows/pr-title.yml @@ -19,9 +19,14 @@ jobs: permissions: pull-requests: write steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + - name: Check title id: lint_pr_title - uses: amannn/action-semantic-pull-request@v6 + uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -40,7 +45,7 @@ jobs: continue-on-error: true - name: Add PR Comment for Invalid Title if: steps.lint_pr_title.outcome == 'failure' - uses: marocchino/sticky-pull-request-comment@v2 + uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # v2.9.4 with: header: pr-title-lint-error message: | @@ -76,7 +81,7 @@ jobs: - name: Remove Comment for Valid Title if: steps.lint_pr_title.outcome == 'success' - uses: marocchino/sticky-pull-request-comment@v2 + uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # v2.9.4 with: header: pr-title-lint-error delete: true diff --git a/.github/workflows/prepare-reth.yml b/.github/workflows/prepare-reth.yml index 17be3767dce..7d9e7b03537 100644 --- a/.github/workflows/prepare-reth.yml +++ b/.github/workflows/prepare-reth.yml @@ -22,6 +22,9 @@ on: type: string description: "Optional cargo package path" +permissions: + contents: read + jobs: prepare-reth: if: github.repository == 'paradigmxyz/reth' @@ -29,14 +32,19 @@ jobs: runs-on: group: Reth steps: - - uses: actions/checkout@v5 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - run: mkdir artifacts - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Build and export reth image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . file: .github/assets/hive/Dockerfile @@ -51,7 +59,7 @@ jobs: - name: Upload reth image id: upload - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: artifacts path: ./artifacts diff --git a/.github/workflows/release-dist.yml b/.github/workflows/release-dist.yml index 57a6f311d0b..6f5816413b3 100644 --- a/.github/workflows/release-dist.yml +++ b/.github/workflows/release-dist.yml @@ -7,12 +7,20 @@ on: release: types: [published] +permissions: + contents: read + jobs: release-homebrew: runs-on: ubuntu-latest steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + - name: Update Homebrew formula - uses: dawidd6/action-homebrew-bump-formula@v5 + uses: dawidd6/action-homebrew-bump-formula@3428a0601bba3173ec0bdcc945be23fa27aa4c31 # v5 with: token: ${{ secrets.HOMEBREW }} no_fork: true diff --git a/.github/workflows/release-reproducible.yml b/.github/workflows/release-reproducible.yml index e0e7f78aa58..dfb3d8067fe 100644 --- a/.github/workflows/release-reproducible.yml +++ b/.github/workflows/release-reproducible.yml @@ -10,11 +10,19 @@ on: env: DOCKER_REPRODUCIBLE_IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/reth-reproducible +permissions: + contents: read + jobs: extract-version: name: extract version runs-on: ubuntu-latest steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + - name: Extract version run: echo "VERSION=$(echo ${GITHUB_REF#refs/tags/})" >> $GITHUB_OUTPUT id: extract_version @@ -29,19 +37,24 @@ jobs: packages: write contents: read steps: - - uses: actions/checkout@v5 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Log in to GitHub Container Registry - uses: docker/login-action@v3 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push reproducible image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . file: ./Dockerfile.reproducible diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 60206b6ace7..41f4e6c828a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,6 +28,11 @@ jobs: name: check dry run runs-on: ubuntu-latest steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + - run: | echo "Dry run value: ${{ github.event.inputs.dry_run }}" echo "Dry run enabled: ${{ github.event.inputs.dry_run == 'true'}}" @@ -37,6 +42,11 @@ jobs: name: extract version runs-on: ubuntu-latest steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + - name: Extract version run: echo "VERSION=${GITHUB_REF_NAME}" >> $GITHUB_OUTPUT id: extract_version @@ -49,8 +59,13 @@ jobs: needs: extract-version if: ${{ github.event.inputs.dry_run != 'true' }} steps: - - uses: actions/checkout@v5 - - uses: dtolnay/rust-toolchain@stable + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable - name: Verify crate version matches tag # Check that the Cargo version starts with the tag, # so that Cargo version 1.4.8 can be matched against both v1.4.8 and v1.4.8-rc.1 @@ -78,7 +93,7 @@ jobs: profile: maxperf allow_fail: false - target: x86_64-apple-darwin - os: macos-13 + os: macos-14 profile: maxperf allow_fail: false - target: aarch64-apple-darwin @@ -99,16 +114,21 @@ jobs: - command: op-build binary: op-reth steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable with: target: ${{ matrix.configs.target }} - name: Install cross main id: cross_main run: | cargo install cross --git https://github.com/cross-rs/cross - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true @@ -141,14 +161,14 @@ jobs: - name: Upload artifact if: ${{ github.event.inputs.dry_run != 'true' }} - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}.tar.gz path: ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}.tar.gz - name: Upload signature if: ${{ github.event.inputs.dry_run != 'true' }} - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}.tar.gz.asc path: ${{ matrix.build.binary }}-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.configs.target }}.tar.gz.asc @@ -166,11 +186,16 @@ jobs: steps: # This is necessary for generating the changelog. # It has to come before "Download Artifacts" or else it deletes the artifacts. - - uses: actions/checkout@v5 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: fetch-depth: 0 - name: Download artifacts - uses: actions/download-artifact@v6 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 - name: Generate full changelog id: changelog run: | @@ -273,6 +298,11 @@ jobs: env: VERSION: ${{ needs.extract-version.outputs.VERSION }} steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + - name: Summarize dry run run: | echo "## 🧪 Release Dry Run Summary" diff --git a/.github/workflows/reproducible-build.yml b/.github/workflows/reproducible-build.yml index b4a93cedaba..26bcae7257b 100644 --- a/.github/workflows/reproducible-build.yml +++ b/.github/workflows/reproducible-build.yml @@ -10,9 +10,14 @@ jobs: name: build reproducible binaries runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable with: target: x86_64-unknown-linux-gnu - name: Install cross main @@ -21,7 +26,7 @@ jobs: - name: Install cargo-cache run: | cargo install cargo-cache - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - name: Build Reth diff --git a/.github/workflows/stage.yml b/.github/workflows/stage.yml index 7225d84cffa..fb8b00a82fa 100644 --- a/.github/workflows/stage.yml +++ b/.github/workflows/stage.yml @@ -29,10 +29,15 @@ jobs: RUST_BACKTRACE: 1 timeout-minutes: 60 steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - name: Build reth diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 297339f53e6..6a2247cca4a 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -7,6 +7,9 @@ on: schedule: - cron: "30 1 * * *" +permissions: + contents: read + jobs: close-issues: runs-on: ubuntu-latest @@ -14,7 +17,12 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@v10 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0 with: days-before-stale: 21 days-before-close: 7 diff --git a/.github/workflows/sync-era.yml b/.github/workflows/sync-era.yml index f2539b2fdc2..d8e9c02edb6 100644 --- a/.github/workflows/sync-era.yml +++ b/.github/workflows/sync-era.yml @@ -39,10 +39,15 @@ jobs: block: 10000 unwind-target: "0x118a6e922a8c6cab221fc5adfe5056d2b72d58c6580e9c5629de55299e2cf8de" steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - name: Build ${{ matrix.chain.bin }} diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml index e57082b83e7..7d54bba612a 100644 --- a/.github/workflows/sync.yml +++ b/.github/workflows/sync.yml @@ -39,10 +39,15 @@ jobs: block: 10000 unwind-target: "0x118a6e922a8c6cab221fc5adfe5056d2b72d58c6580e9c5629de55299e2cf8de" steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - name: Build ${{ matrix.chain.bin }} diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index d9aca93f21c..70c7d4fded7 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -44,15 +44,20 @@ jobs: total_partitions: 2 timeout-minutes: 30 steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - - uses: taiki-e/install-action@nextest + - uses: taiki-e/install-action@65695e4d3f689d823ed155c836d20e98522ad93f # nextest - if: "${{ matrix.type == 'book' }}" - uses: arduino/setup-protoc@v3 + uses: arduino/setup-protoc@c65c819552d16ad3c9b72d9dfd5ba5237b9c906b # v3.0.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Run tests @@ -72,9 +77,14 @@ jobs: RUST_BACKTRACE: 1 timeout-minutes: 30 steps: - - uses: actions/checkout@v5 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - name: Checkout ethereum/tests - uses: actions/checkout@v5 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 with: repository: ethereum/tests ref: 81862e4848585a438d64f911a19b3825f0f4cd95 @@ -90,10 +100,10 @@ jobs: mkdir -p testing/ef-tests/execution-spec-tests URL="https://github.com/ethereum/execution-spec-tests/releases/download/${EEST_TESTS_TAG}/fixtures_stable.tar.gz" curl -L "$URL" | tar -xz --strip-components=1 -C testing/ef-tests/execution-spec-tests - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable - - uses: taiki-e/install-action@nextest - - uses: Swatinem/rust-cache@v2 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + - uses: taiki-e/install-action@65695e4d3f689d823ed155c836d20e98522ad93f # nextest + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - run: cargo nextest run --release -p ef-tests --features "asm-keccak ef-tests" @@ -106,10 +116,15 @@ jobs: RUST_BACKTRACE: 1 timeout-minutes: 30 steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - name: Run doctests @@ -122,7 +137,12 @@ jobs: needs: [test, state, doc] timeout-minutes: 30 steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + - name: Decide whether the needed jobs succeeded or failed - uses: re-actors/alls-green@release/v1 + uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # release/v1 with: jobs: ${{ toJSON(needs) }} diff --git a/.github/workflows/update-superchain.yml b/.github/workflows/update-superchain.yml index f682f35a17d..4f894fac82e 100644 --- a/.github/workflows/update-superchain.yml +++ b/.github/workflows/update-superchain.yml @@ -12,8 +12,13 @@ jobs: update-superchain: runs-on: ubuntu-latest steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 - name: Install required tools run: | @@ -27,7 +32,7 @@ jobs: ./fetch_superchain_config.sh - name: Create Pull Request - uses: peter-evans/create-pull-request@v7 + uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7.0.11 with: commit-message: "chore: update superchain config" title: "chore: update superchain config" diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 81181c2cb1a..1d79ccb56ed 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -15,13 +15,18 @@ jobs: timeout-minutes: 60 steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable with: target: x86_64-pc-windows-gnu - - uses: taiki-e/install-action@cross - - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@853ca955a4c1c9f05f35bcc1f299dbdf4a1b6390 # cross + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - name: mingw-w64 @@ -34,13 +39,18 @@ jobs: timeout-minutes: 60 steps: - - uses: actions/checkout@v5 - - uses: rui314/setup-mold@v1 - - uses: dtolnay/rust-toolchain@stable + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1 + with: + egress-policy: audit + + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable with: target: x86_64-pc-windows-gnu - - uses: taiki-e/install-action@cross - - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@853ca955a4c1c9f05f35bcc1f299dbdf4a1b6390 # cross + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2 with: cache-on-failure: true - name: mingw-w64 diff --git a/Cargo.lock b/Cargo.lock index b7c8618f423..483777ce52b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3193,7 +3193,7 @@ dependencies = [ [[package]] name = "ef-test-runner" -version = "1.9.0" +version = "1.9.3" dependencies = [ "clap", "ef-tests", @@ -3201,7 +3201,7 @@ dependencies = [ [[package]] name = "ef-tests" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -3681,7 +3681,7 @@ dependencies = [ [[package]] name = "example-full-contract-state" -version = "1.9.0" +version = "1.9.3" dependencies = [ "eyre", "reth-ethereum", @@ -3820,7 +3820,7 @@ dependencies = [ [[package]] name = "exex-subscription" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-primitives", "clap", @@ -6218,7 +6218,7 @@ dependencies = [ [[package]] name = "op-reth" -version = "1.9.0" +version = "1.9.3" dependencies = [ "clap", "reth-cli-util", @@ -6236,9 +6236,9 @@ dependencies = [ [[package]] name = "op-revm" -version = "12.0.0" +version = "12.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e599c71e91670fb922e3cdcb04783caed1226352da19d674bd001b3bf2bc433" +checksum = "e31622d03b29c826e48800f4c8f389c8a9c440eb796a3e35203561a288f12985" dependencies = [ "auto_impl", "revm", @@ -7296,7 +7296,7 @@ checksum = "6b3789b30bd25ba102de4beabd95d21ac45b69b1be7d14522bab988c526d6799" [[package]] name = "reth" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-rpc-types", "aquamarine", @@ -7343,7 +7343,7 @@ dependencies = [ [[package]] name = "reth-basic-payload-builder" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -7366,7 +7366,7 @@ dependencies = [ [[package]] name = "reth-bench" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-eips", "alloy-json-rpc", @@ -7405,7 +7405,7 @@ dependencies = [ [[package]] name = "reth-bench-compare" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-primitives", "alloy-provider", @@ -7431,7 +7431,7 @@ dependencies = [ [[package]] name = "reth-chain-state" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -7463,7 +7463,7 @@ dependencies = [ [[package]] name = "reth-chainspec" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-chains", "alloy-consensus", @@ -7483,7 +7483,7 @@ dependencies = [ [[package]] name = "reth-cli" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-genesis", "clap", @@ -7496,7 +7496,7 @@ dependencies = [ [[package]] name = "reth-cli-commands" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-chains", "alloy-consensus", @@ -7578,7 +7578,7 @@ dependencies = [ [[package]] name = "reth-cli-runner" -version = "1.9.0" +version = "1.9.3" dependencies = [ "reth-tasks", "tokio", @@ -7587,7 +7587,7 @@ dependencies = [ [[package]] name = "reth-cli-util" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-eips", "alloy-primitives", @@ -7607,7 +7607,7 @@ dependencies = [ [[package]] name = "reth-codecs" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -7631,7 +7631,7 @@ dependencies = [ [[package]] name = "reth-codecs-derive" -version = "1.9.0" +version = "1.9.3" dependencies = [ "proc-macro2", "quote", @@ -7641,7 +7641,7 @@ dependencies = [ [[package]] name = "reth-config" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-primitives", "eyre", @@ -7658,7 +7658,7 @@ dependencies = [ [[package]] name = "reth-consensus" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -7670,7 +7670,7 @@ dependencies = [ [[package]] name = "reth-consensus-common" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -7684,7 +7684,7 @@ dependencies = [ [[package]] name = "reth-consensus-debug-client" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -7709,7 +7709,7 @@ dependencies = [ [[package]] name = "reth-db" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -7743,7 +7743,7 @@ dependencies = [ [[package]] name = "reth-db-api" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-genesis", @@ -7773,7 +7773,7 @@ dependencies = [ [[package]] name = "reth-db-common" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-genesis", @@ -7803,7 +7803,7 @@ dependencies = [ [[package]] name = "reth-db-models" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-eips", "alloy-primitives", @@ -7819,7 +7819,7 @@ dependencies = [ [[package]] name = "reth-discv4" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -7845,7 +7845,7 @@ dependencies = [ [[package]] name = "reth-discv5" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -7870,7 +7870,7 @@ dependencies = [ [[package]] name = "reth-dns-discovery" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-chains", "alloy-primitives", @@ -7898,7 +7898,7 @@ dependencies = [ [[package]] name = "reth-downloaders" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -7936,7 +7936,7 @@ dependencies = [ [[package]] name = "reth-e2e-test-utils" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -7993,7 +7993,7 @@ dependencies = [ [[package]] name = "reth-ecies" -version = "1.9.0" +version = "1.9.3" dependencies = [ "aes", "alloy-primitives", @@ -8023,7 +8023,7 @@ dependencies = [ [[package]] name = "reth-engine-local" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -8046,7 +8046,7 @@ dependencies = [ [[package]] name = "reth-engine-primitives" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -8070,7 +8070,7 @@ dependencies = [ [[package]] name = "reth-engine-service" -version = "1.9.0" +version = "1.9.3" dependencies = [ "futures", "pin-project", @@ -8099,7 +8099,7 @@ dependencies = [ [[package]] name = "reth-engine-tree" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -8170,7 +8170,7 @@ dependencies = [ [[package]] name = "reth-engine-util" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-rpc-types-engine", @@ -8197,7 +8197,7 @@ dependencies = [ [[package]] name = "reth-era" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -8219,7 +8219,7 @@ dependencies = [ [[package]] name = "reth-era-downloader" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-primitives", "bytes", @@ -8236,7 +8236,7 @@ dependencies = [ [[package]] name = "reth-era-utils" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -8262,7 +8262,7 @@ dependencies = [ [[package]] name = "reth-errors" -version = "1.9.0" +version = "1.9.3" dependencies = [ "reth-consensus", "reth-execution-errors", @@ -8272,7 +8272,7 @@ dependencies = [ [[package]] name = "reth-eth-wire" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-chains", "alloy-consensus", @@ -8310,7 +8310,7 @@ dependencies = [ [[package]] name = "reth-eth-wire-types" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-chains", "alloy-consensus", @@ -8335,7 +8335,7 @@ dependencies = [ [[package]] name = "reth-ethereum" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-rpc-types-engine", "alloy-rpc-types-eth", @@ -8375,7 +8375,7 @@ dependencies = [ [[package]] name = "reth-ethereum-cli" -version = "1.9.0" +version = "1.9.3" dependencies = [ "clap", "eyre", @@ -8399,7 +8399,7 @@ dependencies = [ [[package]] name = "reth-ethereum-consensus" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -8415,7 +8415,7 @@ dependencies = [ [[package]] name = "reth-ethereum-engine-primitives" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-eips", "alloy-primitives", @@ -8433,7 +8433,7 @@ dependencies = [ [[package]] name = "reth-ethereum-forks" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-eip2124", "alloy-hardforks", @@ -8446,7 +8446,7 @@ dependencies = [ [[package]] name = "reth-ethereum-payload-builder" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -8474,7 +8474,7 @@ dependencies = [ [[package]] name = "reth-ethereum-primitives" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -8501,7 +8501,7 @@ dependencies = [ [[package]] name = "reth-etl" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-primitives", "rayon", @@ -8511,7 +8511,7 @@ dependencies = [ [[package]] name = "reth-evm" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -8535,7 +8535,7 @@ dependencies = [ [[package]] name = "reth-evm-ethereum" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -8559,7 +8559,7 @@ dependencies = [ [[package]] name = "reth-execution-errors" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-evm", "alloy-primitives", @@ -8571,7 +8571,7 @@ dependencies = [ [[package]] name = "reth-execution-types" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -8591,7 +8591,7 @@ dependencies = [ [[package]] name = "reth-exex" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -8635,7 +8635,7 @@ dependencies = [ [[package]] name = "reth-exex-test-utils" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-eips", "eyre", @@ -8666,7 +8666,7 @@ dependencies = [ [[package]] name = "reth-exex-types" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-eips", "alloy-primitives", @@ -8683,7 +8683,7 @@ dependencies = [ [[package]] name = "reth-fs-util" -version = "1.9.0" +version = "1.9.3" dependencies = [ "serde", "serde_json", @@ -8692,7 +8692,7 @@ dependencies = [ [[package]] name = "reth-invalid-block-hooks" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -8725,7 +8725,7 @@ dependencies = [ [[package]] name = "reth-ipc" -version = "1.9.0" +version = "1.9.3" dependencies = [ "bytes", "futures", @@ -8747,7 +8747,7 @@ dependencies = [ [[package]] name = "reth-libmdbx" -version = "1.9.0" +version = "1.9.3" dependencies = [ "bitflags 2.10.0", "byteorder", @@ -8765,7 +8765,7 @@ dependencies = [ [[package]] name = "reth-mdbx-sys" -version = "1.9.0" +version = "1.9.3" dependencies = [ "bindgen 0.71.1", "cc", @@ -8773,7 +8773,7 @@ dependencies = [ [[package]] name = "reth-metrics" -version = "1.9.0" +version = "1.9.3" dependencies = [ "futures", "metrics", @@ -8784,14 +8784,14 @@ dependencies = [ [[package]] name = "reth-net-banlist" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-primitives", ] [[package]] name = "reth-net-nat" -version = "1.9.0" +version = "1.9.3" dependencies = [ "futures-util", "if-addrs", @@ -8805,7 +8805,7 @@ dependencies = [ [[package]] name = "reth-network" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -8865,7 +8865,7 @@ dependencies = [ [[package]] name = "reth-network-api" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -8889,7 +8889,7 @@ dependencies = [ [[package]] name = "reth-network-p2p" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -8911,7 +8911,7 @@ dependencies = [ [[package]] name = "reth-network-peers" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -8928,7 +8928,7 @@ dependencies = [ [[package]] name = "reth-network-types" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-eip2124", "humantime-serde", @@ -8941,7 +8941,7 @@ dependencies = [ [[package]] name = "reth-nippy-jar" -version = "1.9.0" +version = "1.9.3" dependencies = [ "anyhow", "bincode 1.3.3", @@ -8959,7 +8959,7 @@ dependencies = [ [[package]] name = "reth-node-api" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-rpc-types-engine", "eyre", @@ -8982,7 +8982,7 @@ dependencies = [ [[package]] name = "reth-node-builder" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9053,7 +9053,7 @@ dependencies = [ [[package]] name = "reth-node-core" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9096,6 +9096,7 @@ dependencies = [ "serde", "shellexpand", "strum 0.27.2", + "thiserror 2.0.17", "tokio", "toml", "tracing", @@ -9106,7 +9107,7 @@ dependencies = [ [[package]] name = "reth-node-ethereum" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-contract", @@ -9159,7 +9160,7 @@ dependencies = [ [[package]] name = "reth-node-ethstats" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -9182,7 +9183,7 @@ dependencies = [ [[package]] name = "reth-node-events" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9205,7 +9206,7 @@ dependencies = [ [[package]] name = "reth-node-metrics" -version = "1.9.0" +version = "1.9.3" dependencies = [ "eyre", "http", @@ -9227,7 +9228,7 @@ dependencies = [ [[package]] name = "reth-node-types" -version = "1.9.0" +version = "1.9.3" dependencies = [ "reth-chainspec", "reth-db-api", @@ -9238,7 +9239,7 @@ dependencies = [ [[package]] name = "reth-op" -version = "1.9.0" +version = "1.9.3" dependencies = [ "reth-chainspec", "reth-cli-util", @@ -9278,7 +9279,7 @@ dependencies = [ [[package]] name = "reth-optimism-chainspec" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-chains", "alloy-consensus", @@ -9306,7 +9307,7 @@ dependencies = [ [[package]] name = "reth-optimism-cli" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9357,7 +9358,7 @@ dependencies = [ [[package]] name = "reth-optimism-consensus" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-chains", "alloy-consensus", @@ -9388,7 +9389,7 @@ dependencies = [ [[package]] name = "reth-optimism-evm" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9417,7 +9418,7 @@ dependencies = [ [[package]] name = "reth-optimism-flashblocks" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9456,7 +9457,7 @@ dependencies = [ [[package]] name = "reth-optimism-forks" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-op-hardforks", "alloy-primitives", @@ -9466,7 +9467,7 @@ dependencies = [ [[package]] name = "reth-optimism-node" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-genesis", @@ -9524,7 +9525,7 @@ dependencies = [ [[package]] name = "reth-optimism-payload-builder" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9563,7 +9564,7 @@ dependencies = [ [[package]] name = "reth-optimism-primitives" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9590,7 +9591,7 @@ dependencies = [ [[package]] name = "reth-optimism-rpc" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9652,7 +9653,7 @@ dependencies = [ [[package]] name = "reth-optimism-storage" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "reth-codecs", @@ -9664,7 +9665,7 @@ dependencies = [ [[package]] name = "reth-optimism-txpool" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9701,7 +9702,7 @@ dependencies = [ [[package]] name = "reth-payload-builder" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -9721,7 +9722,7 @@ dependencies = [ [[package]] name = "reth-payload-builder-primitives" -version = "1.9.0" +version = "1.9.3" dependencies = [ "pin-project", "reth-payload-primitives", @@ -9732,7 +9733,7 @@ dependencies = [ [[package]] name = "reth-payload-primitives" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-eips", "alloy-primitives", @@ -9752,7 +9753,7 @@ dependencies = [ [[package]] name = "reth-payload-util" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -9761,7 +9762,7 @@ dependencies = [ [[package]] name = "reth-payload-validator" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-rpc-types-engine", @@ -9770,7 +9771,7 @@ dependencies = [ [[package]] name = "reth-primitives" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9792,7 +9793,7 @@ dependencies = [ [[package]] name = "reth-primitives-traits" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9829,7 +9830,7 @@ dependencies = [ [[package]] name = "reth-provider" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9877,8 +9878,9 @@ dependencies = [ [[package]] name = "reth-prune" -version = "1.9.0" +version = "1.9.3" dependencies = [ + "alloy-consensus", "alloy-eips", "alloy-primitives", "assert_matches", @@ -9907,11 +9909,11 @@ dependencies = [ [[package]] name = "reth-prune-db" -version = "1.9.0" +version = "1.9.3" [[package]] name = "reth-prune-types" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-primitives", "arbitrary", @@ -9930,7 +9932,7 @@ dependencies = [ [[package]] name = "reth-ress-protocol" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -9956,7 +9958,7 @@ dependencies = [ [[package]] name = "reth-ress-provider" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -9982,7 +9984,7 @@ dependencies = [ [[package]] name = "reth-revm" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -9996,7 +9998,7 @@ dependencies = [ [[package]] name = "reth-rpc" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -10079,7 +10081,7 @@ dependencies = [ [[package]] name = "reth-rpc-api" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-eips", "alloy-genesis", @@ -10106,7 +10108,7 @@ dependencies = [ [[package]] name = "reth-rpc-api-testing-util" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-eips", "alloy-primitives", @@ -10125,7 +10127,7 @@ dependencies = [ [[package]] name = "reth-rpc-builder" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-eips", "alloy-network", @@ -10180,7 +10182,7 @@ dependencies = [ [[package]] name = "reth-rpc-convert" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-json-rpc", @@ -10207,7 +10209,7 @@ dependencies = [ [[package]] name = "reth-rpc-e2e-tests" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-genesis", "alloy-rpc-types-engine", @@ -10227,7 +10229,7 @@ dependencies = [ [[package]] name = "reth-rpc-engine-api" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-eips", "alloy-primitives", @@ -10263,7 +10265,7 @@ dependencies = [ [[package]] name = "reth-rpc-eth-api" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -10306,7 +10308,7 @@ dependencies = [ [[package]] name = "reth-rpc-eth-types" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10353,7 +10355,7 @@ dependencies = [ [[package]] name = "reth-rpc-layer" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-rpc-types-engine", "http", @@ -10370,7 +10372,7 @@ dependencies = [ [[package]] name = "reth-rpc-server-types" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-eips", "alloy-primitives", @@ -10385,7 +10387,7 @@ dependencies = [ [[package]] name = "reth-stages" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10442,7 +10444,7 @@ dependencies = [ [[package]] name = "reth-stages-api" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-eips", "alloy-primitives", @@ -10471,7 +10473,7 @@ dependencies = [ [[package]] name = "reth-stages-types" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-primitives", "arbitrary", @@ -10487,7 +10489,7 @@ dependencies = [ [[package]] name = "reth-stateless" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -10514,7 +10516,7 @@ dependencies = [ [[package]] name = "reth-static-file" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-primitives", "assert_matches", @@ -10537,7 +10539,7 @@ dependencies = [ [[package]] name = "reth-static-file-types" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-primitives", "clap", @@ -10549,7 +10551,7 @@ dependencies = [ [[package]] name = "reth-storage-api" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10571,7 +10573,7 @@ dependencies = [ [[package]] name = "reth-storage-errors" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-eips", "alloy-primitives", @@ -10586,7 +10588,7 @@ dependencies = [ [[package]] name = "reth-storage-rpc-provider" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10615,7 +10617,7 @@ dependencies = [ [[package]] name = "reth-tasks" -version = "1.9.0" +version = "1.9.3" dependencies = [ "auto_impl", "dyn-clone", @@ -10632,7 +10634,7 @@ dependencies = [ [[package]] name = "reth-testing-utils" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10647,7 +10649,7 @@ dependencies = [ [[package]] name = "reth-tokio-util" -version = "1.9.0" +version = "1.9.3" dependencies = [ "tokio", "tokio-stream", @@ -10656,7 +10658,7 @@ dependencies = [ [[package]] name = "reth-tracing" -version = "1.9.0" +version = "1.9.3" dependencies = [ "clap", "eyre", @@ -10672,7 +10674,7 @@ dependencies = [ [[package]] name = "reth-tracing-otlp" -version = "1.9.0" +version = "1.9.3" dependencies = [ "clap", "eyre", @@ -10688,7 +10690,7 @@ dependencies = [ [[package]] name = "reth-transaction-pool" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10736,7 +10738,7 @@ dependencies = [ [[package]] name = "reth-trie" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10769,7 +10771,7 @@ dependencies = [ [[package]] name = "reth-trie-common" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-genesis", @@ -10802,7 +10804,7 @@ dependencies = [ [[package]] name = "reth-trie-db" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -10827,7 +10829,7 @@ dependencies = [ [[package]] name = "reth-trie-parallel" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -10857,7 +10859,7 @@ dependencies = [ [[package]] name = "reth-trie-sparse" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -10890,7 +10892,7 @@ dependencies = [ [[package]] name = "reth-trie-sparse-parallel" -version = "1.9.0" +version = "1.9.3" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -10919,16 +10921,16 @@ dependencies = [ [[package]] name = "reth-zstd-compressors" -version = "1.9.0" +version = "1.9.3" dependencies = [ "zstd", ] [[package]] name = "revm" -version = "31.0.0" +version = "31.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7bba993ce958f0b6eb23d2644ea8360982cb60baffedf961441e36faba6a2ca" +checksum = "bb67a5223602113cae59a305acde2d9936bc18f2478dda879a6124b267cebfb6" dependencies = [ "revm-bytecode", "revm-context", @@ -10945,9 +10947,9 @@ dependencies = [ [[package]] name = "revm-bytecode" -version = "7.1.0" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2b51c414b7e79edd4a0569d06e2c4c029f8b60e5f3ee3e2fa21dc6c3717ee3" +checksum = "e2c6b5e6e8dd1e28a4a60e5f46615d4ef0809111c9e63208e55b5c7058200fb0" dependencies = [ "bitvec", "phf", @@ -10957,9 +10959,9 @@ dependencies = [ [[package]] name = "revm-context" -version = "11.0.0" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f69efee45130bd9e5b0a7af27552fddc70bc161dafed533c2f818a2d1eb654e6" +checksum = "92850e150f4f99d46c05a20ad0cd09286a7ad4ee21866fffb87101de6e602231" dependencies = [ "bitvec", "cfg-if", @@ -10974,9 +10976,9 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "12.0.0" +version = "12.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce2525e93db0ae2a3ec7dcde5443dfdb6fbf321c5090380d775730c67bc6cee" +checksum = "f6d701e2c2347d65216b066489ab22a0a8e1f7b2568256110d73a7d5eff3385c" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -10990,9 +10992,9 @@ dependencies = [ [[package]] name = "revm-database" -version = "9.0.3" +version = "9.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2602625aa11ab1eda8e208e96b652c0bfa989b86c104a36537a62b081228af9" +checksum = "7b6c15bb255481fcf29f5ef7c97f00ed4c28a6ab6c490d77b990d73603031569" dependencies = [ "alloy-eips", "revm-bytecode", @@ -11004,9 +11006,9 @@ dependencies = [ [[package]] name = "revm-database-interface" -version = "8.0.4" +version = "8.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58a4621143d6515e32f969306d9c85797ae0d3fe0c74784f1fda02ba441e5a08" +checksum = "8cce03e3780287b07abe58faf4a7f5d8be7e81321f93ccf3343c8f7755602bae" dependencies = [ "auto_impl", "either", @@ -11017,9 +11019,9 @@ dependencies = [ [[package]] name = "revm-handler" -version = "12.0.0" +version = "12.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e756198d43b6c4c5886548ffbc4594412d1a82b81723525c6e85ed6da0e91c5f" +checksum = "b45418ed95cfdf0cb19effdbb7633cf2144cab7fb0e6ffd6b0eb9117a50adff6" dependencies = [ "auto_impl", "derive-where", @@ -11036,9 +11038,9 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "12.0.0" +version = "12.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fdd1e74cc99c6173c8692b6e480291e2ad0c21c716d9dc16e937ab2e0da219" +checksum = "c99801eac7da06cc112df2244bd5a64024f4ef21240e923b26e73c4b4a0e5da6" dependencies = [ "auto_impl", "either", @@ -11074,9 +11076,9 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "29.0.0" +version = "29.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44efb7c2f4034a5bfd3d71ebfed076e48ac75e4972f1c117f2a20befac7716cd" +checksum = "22789ce92c5808c70185e3bc49732f987dc6fd907f77828c8d3470b2299c9c65" dependencies = [ "revm-bytecode", "revm-context-interface", @@ -11087,9 +11089,9 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "29.0.0" +version = "29.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585098ede6d84d6fc6096ba804b8e221c44dc77679571d32664a55e665aa236b" +checksum = "968b124028960201abf6d6bf8e223f15fadebb4307df6b7dc9244a0aab5d2d05" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -11112,9 +11114,9 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "21.0.1" +version = "21.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "536f30e24c3c2bf0d3d7d20fa9cf99b93040ed0f021fd9301c78cddb0dacda13" +checksum = "29e161db429d465c09ba9cbff0df49e31049fe6b549e28eb0b7bd642fcbd4412" dependencies = [ "alloy-primitives", "num_enum", @@ -11124,9 +11126,9 @@ dependencies = [ [[package]] name = "revm-state" -version = "8.1.0" +version = "8.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a0b4873815e31cbc3e5b183b9128b86c09a487c027aaf8cc5cf4b9688878f9b" +checksum = "7d8be953b7e374dbdea0773cf360debed8df394ea8d82a8b240a6b5da37592fc" dependencies = [ "bitflags 2.10.0", "revm-bytecode", diff --git a/Cargo.toml b/Cargo.toml index 6e6f4226598..4e27936d255 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "1.9.0" +version = "1.9.3" edition = "2024" rust-version = "1.88" license = "MIT OR Apache-2.0" @@ -466,17 +466,17 @@ reth-ress-protocol = { path = "crates/ress/protocol" } reth-ress-provider = { path = "crates/ress/provider" } # revm -revm = { version = "31.0.0", default-features = false } -revm-bytecode = { version = "7.1.0", default-features = false } -revm-database = { version = "9.0.3", default-features = false } -revm-state = { version = "8.1.0", default-features = false } -revm-primitives = { version = "21.0.1", default-features = false } -revm-interpreter = { version = "29.0.0", default-features = false } -revm-inspector = { version = "12.0.0", default-features = false } -revm-context = { version = "11.0.0", default-features = false } -revm-context-interface = { version = "12.0.0", default-features = false } -revm-database-interface = { version = "8.0.4", default-features = false } -op-revm = { version = "12.0.0", default-features = false } +revm = { version = "31.0.2", default-features = false } +revm-bytecode = { version = "7.1.1", default-features = false } +revm-database = { version = "9.0.5", default-features = false } +revm-state = { version = "8.1.1", default-features = false } +revm-primitives = { version = "21.0.2", default-features = false } +revm-interpreter = { version = "29.0.1", default-features = false } +revm-inspector = { version = "12.0.2", default-features = false } +revm-context = { version = "11.0.2", default-features = false } +revm-context-interface = { version = "12.0.1", default-features = false } +revm-database-interface = { version = "8.0.5", default-features = false } +op-revm = { version = "12.0.2", default-features = false } revm-inspectors = "0.32.0" # eth diff --git a/crates/config/src/config.rs b/crates/config/src/config.rs index dd2e7046b0c..5ff2431bb56 100644 --- a/crates/config/src/config.rs +++ b/crates/config/src/config.rs @@ -33,7 +33,7 @@ pub struct Config { impl Config { /// Sets the pruning configuration. - pub const fn set_prune_config(&mut self, prune_config: PruneConfig) { + pub fn set_prune_config(&mut self, prune_config: PruneConfig) { self.prune = prune_config; } } @@ -451,14 +451,13 @@ impl PruneConfig { } /// Returns whether there is any kind of receipt pruning configuration. - pub const fn has_receipts_pruning(&self) -> bool { - self.segments.receipts.is_some() + pub fn has_receipts_pruning(&self) -> bool { + self.segments.receipts.is_some() || !self.segments.receipts_log_filter.is_empty() } /// Merges another `PruneConfig` into this one, taking values from the other config if and only /// if the corresponding value in this config is not set. pub fn merge(&mut self, other: Self) { - #[expect(deprecated)] let Self { block_interval, segments: @@ -470,7 +469,7 @@ impl PruneConfig { storage_history, bodies_history, merkle_changesets, - receipts_log_filter: (), + receipts_log_filter, }, } = other; @@ -488,6 +487,10 @@ impl PruneConfig { self.segments.bodies_history = self.segments.bodies_history.or(bodies_history); // Merkle changesets is not optional, so we just replace it if provided self.segments.merkle_changesets = merkle_changesets; + + if self.segments.receipts_log_filter.0.is_empty() && !receipts_log_filter.0.is_empty() { + self.segments.receipts_log_filter = receipts_log_filter; + } } } @@ -514,9 +517,10 @@ where mod tests { use super::{Config, EXTENSION}; use crate::PruneConfig; + use alloy_primitives::Address; use reth_network_peers::TrustedPeer; - use reth_prune_types::{PruneMode, PruneModes}; - use std::{path::Path, str::FromStr, time::Duration}; + use reth_prune_types::{PruneMode, PruneModes, ReceiptsLogPruneConfig}; + use std::{collections::BTreeMap, path::Path, str::FromStr, time::Duration}; fn with_tempdir(filename: &str, proc: fn(&std::path::Path)) { let temp_dir = tempfile::tempdir().unwrap(); @@ -1005,8 +1009,10 @@ receipts = 'full' storage_history: Some(PruneMode::Before(5000)), bodies_history: None, merkle_changesets: PruneMode::Before(0), - #[expect(deprecated)] - receipts_log_filter: (), + receipts_log_filter: ReceiptsLogPruneConfig(BTreeMap::from([( + Address::random(), + PruneMode::Full, + )])), }, }; @@ -1020,11 +1026,14 @@ receipts = 'full' storage_history: Some(PruneMode::Distance(3000)), bodies_history: None, merkle_changesets: PruneMode::Distance(10000), - #[expect(deprecated)] - receipts_log_filter: (), + receipts_log_filter: ReceiptsLogPruneConfig(BTreeMap::from([ + (Address::random(), PruneMode::Distance(1000)), + (Address::random(), PruneMode::Before(2000)), + ])), }, }; + let original_filter = config1.segments.receipts_log_filter.clone(); config1.merge(config2); // Check that the configuration has been merged. Any configuration present in config1 @@ -1036,6 +1045,7 @@ receipts = 'full' assert_eq!(config1.segments.account_history, Some(PruneMode::Distance(2000))); assert_eq!(config1.segments.storage_history, Some(PruneMode::Before(5000))); assert_eq!(config1.segments.merkle_changesets, PruneMode::Distance(10000)); + assert_eq!(config1.segments.receipts_log_filter, original_filter); } #[test] diff --git a/crates/exex/exex/src/backfill/factory.rs b/crates/exex/exex/src/backfill/factory.rs index 29734b905e2..d9a51bc47a7 100644 --- a/crates/exex/exex/src/backfill/factory.rs +++ b/crates/exex/exex/src/backfill/factory.rs @@ -39,7 +39,7 @@ impl BackfillJobFactory { } /// Sets the prune modes - pub const fn with_prune_modes(mut self, prune_modes: PruneModes) -> Self { + pub fn with_prune_modes(mut self, prune_modes: PruneModes) -> Self { self.prune_modes = prune_modes; self } diff --git a/crates/node/builder/src/launch/common.rs b/crates/node/builder/src/launch/common.rs index c049ddfbf21..95909e34710 100644 --- a/crates/node/builder/src/launch/common.rs +++ b/crates/node/builder/src/launch/common.rs @@ -405,14 +405,13 @@ impl LaunchContextWith, - /// Receipts Log Filter - #[arg( - long = "prune.receipts-log-filter", - alias = "prune.receiptslogfilter", - value_name = "FILTER_CONFIG", - hide = true - )] - #[deprecated] - pub receipts_log_filter: Option, + // Receipts Log Filter + /// Configure receipts log filter. Format: + /// <`address`>:<`prune_mode`>... where <`prune_mode`> can be 'full', 'distance:<`blocks`>', or + /// 'before:<`block_number`>' + #[arg(long = "prune.receiptslogfilter", value_name = "FILTER_CONFIG", conflicts_with_all = &["receipts_full", "receipts_pre_merge", "receipts_distance", "receipts_before"], value_parser = parse_receipts_log_filter)] + pub receipts_log_filter: Option, // Account History /// Prunes all account history. @@ -136,8 +132,7 @@ impl PruningArgs { .block_number() .map(PruneMode::Before), merkle_changesets: PruneMode::Distance(MINIMUM_PRUNING_DISTANCE), - #[expect(deprecated)] - receipts_log_filter: (), + receipts_log_filter: Default::default(), }, } } @@ -164,14 +159,13 @@ impl PruningArgs { if let Some(mode) = self.storage_history_prune_mode() { config.segments.storage_history = Some(mode); } - - // Log warning if receipts_log_filter is set (deprecated feature) - #[expect(deprecated)] - if self.receipts_log_filter.is_some() { - tracing::warn!( - target: "reth::cli", - "The --prune.receiptslogfilter flag is deprecated and has no effect. It will be removed in a future release." - ); + if let Some(receipt_logs) = + self.receipts_log_filter.as_ref().filter(|c| !c.is_empty()).cloned() + { + config.segments.receipts_log_filter = receipt_logs; + // need to remove the receipts segment filter entirely because that takes precedence + // over the logs filter + config.segments.receipts.take(); } config.is_default().not().then_some(config) @@ -259,3 +253,141 @@ impl PruningArgs { } } } + +/// Parses `,` separated pruning info into [`ReceiptsLogPruneConfig`]. +pub(crate) fn parse_receipts_log_filter( + value: &str, +) -> Result { + let mut config = BTreeMap::new(); + // Split out each of the filters. + let filters = value.split(','); + for filter in filters { + let parts: Vec<&str> = filter.split(':').collect(); + if parts.len() < 2 { + return Err(ReceiptsLogError::InvalidFilterFormat(filter.to_string())); + } + // Parse the address + let address = parts[0] + .parse::
() + .map_err(|_| ReceiptsLogError::InvalidAddress(parts[0].to_string()))?; + + // Parse the prune mode + let prune_mode = match parts[1] { + "full" => PruneMode::Full, + s if s.starts_with("distance") => { + if parts.len() < 3 { + return Err(ReceiptsLogError::InvalidFilterFormat(filter.to_string())); + } + let distance = + parts[2].parse::().map_err(ReceiptsLogError::InvalidDistance)?; + PruneMode::Distance(distance) + } + s if s.starts_with("before") => { + if parts.len() < 3 { + return Err(ReceiptsLogError::InvalidFilterFormat(filter.to_string())); + } + let block_number = + parts[2].parse::().map_err(ReceiptsLogError::InvalidBlockNumber)?; + PruneMode::Before(block_number) + } + _ => return Err(ReceiptsLogError::InvalidPruneMode(parts[1].to_string())), + }; + config.insert(address, prune_mode); + } + Ok(ReceiptsLogPruneConfig(config)) +} + +#[cfg(test)] +mod tests { + use super::*; + use alloy_primitives::address; + use clap::Parser; + + /// A helper type to parse Args more easily + #[derive(Parser)] + struct CommandParser { + #[command(flatten)] + args: T, + } + + #[test] + fn pruning_args_sanity_check() { + let args = CommandParser::::parse_from([ + "reth", + "--prune.receiptslogfilter", + "0x0000000000000000000000000000000000000003:before:5000000", + ]) + .args; + let mut config = ReceiptsLogPruneConfig::default(); + config.0.insert( + address!("0x0000000000000000000000000000000000000003"), + PruneMode::Before(5000000), + ); + assert_eq!(args.receipts_log_filter, Some(config)); + } + + #[test] + fn parse_receiptslogfilter() { + let default_args = PruningArgs::default(); + let args = CommandParser::::parse_from(["reth"]).args; + assert_eq!(args, default_args); + } + + #[test] + fn test_parse_receipts_log_filter() { + let filter1 = "0x0000000000000000000000000000000000000001:full"; + let filter2 = "0x0000000000000000000000000000000000000002:distance:1000"; + let filter3 = "0x0000000000000000000000000000000000000003:before:5000000"; + let filters = [filter1, filter2, filter3].join(","); + + // Args can be parsed. + let result = parse_receipts_log_filter(&filters); + assert!(result.is_ok()); + let config = result.unwrap(); + assert_eq!(config.0.len(), 3); + + // Check that the args were parsed correctly. + let addr1: Address = "0x0000000000000000000000000000000000000001".parse().unwrap(); + let addr2: Address = "0x0000000000000000000000000000000000000002".parse().unwrap(); + let addr3: Address = "0x0000000000000000000000000000000000000003".parse().unwrap(); + + assert_eq!(config.0.get(&addr1), Some(&PruneMode::Full)); + assert_eq!(config.0.get(&addr2), Some(&PruneMode::Distance(1000))); + assert_eq!(config.0.get(&addr3), Some(&PruneMode::Before(5000000))); + } + + #[test] + fn test_parse_receipts_log_filter_invalid_filter_format() { + let result = parse_receipts_log_filter("invalid_format"); + assert!(matches!(result, Err(ReceiptsLogError::InvalidFilterFormat(_)))); + } + + #[test] + fn test_parse_receipts_log_filter_invalid_address() { + let result = parse_receipts_log_filter("invalid_address:full"); + assert!(matches!(result, Err(ReceiptsLogError::InvalidAddress(_)))); + } + + #[test] + fn test_parse_receipts_log_filter_invalid_prune_mode() { + let result = + parse_receipts_log_filter("0x0000000000000000000000000000000000000000:invalid_mode"); + assert!(matches!(result, Err(ReceiptsLogError::InvalidPruneMode(_)))); + } + + #[test] + fn test_parse_receipts_log_filter_invalid_distance() { + let result = parse_receipts_log_filter( + "0x0000000000000000000000000000000000000000:distance:invalid_distance", + ); + assert!(matches!(result, Err(ReceiptsLogError::InvalidDistance(_)))); + } + + #[test] + fn test_parse_receipts_log_filter_invalid_block_number() { + let result = parse_receipts_log_filter( + "0x0000000000000000000000000000000000000000:before:invalid_block", + ); + assert!(matches!(result, Err(ReceiptsLogError::InvalidBlockNumber(_)))); + } +} diff --git a/crates/optimism/chainspec/res/superchain-configs.tar b/crates/optimism/chainspec/res/superchain-configs.tar index 80345a28438..2ed30f474b8 100644 Binary files a/crates/optimism/chainspec/res/superchain-configs.tar and b/crates/optimism/chainspec/res/superchain-configs.tar differ diff --git a/crates/optimism/chainspec/res/superchain_registry_commit b/crates/optimism/chainspec/res/superchain_registry_commit index d37cde1bb4a..239646ec046 100644 --- a/crates/optimism/chainspec/res/superchain_registry_commit +++ b/crates/optimism/chainspec/res/superchain_registry_commit @@ -1 +1 @@ -9e3f71cee0e4e2acb4864cb00f5fbee3555d8e9f +59e22d265b7a423b7f51a67a722471a6f3c3cc39 diff --git a/crates/optimism/payload/src/payload.rs b/crates/optimism/payload/src/payload.rs index 6f530acd853..41b825a2b72 100644 --- a/crates/optimism/payload/src/payload.rs +++ b/crates/optimism/payload/src/payload.rs @@ -342,6 +342,9 @@ where /// Generates the payload id for the configured payload from the [`OpPayloadAttributes`]. /// /// Returns an 8-byte identifier by hashing the payload components with sha256 hash. +/// +/// Note: This must be updated whenever the [`OpPayloadAttributes`] changes for a hardfork. +/// See also pub fn payload_id_optimism( parent: &B256, attributes: &OpPayloadAttributes, @@ -387,6 +390,10 @@ pub fn payload_id_optimism( hasher.update(eip_1559_params.as_slice()); } + if let Some(min_base_fee) = attributes.min_base_fee { + hasher.update(min_base_fee.to_be_bytes()); + } + let mut out = hasher.finalize(); out[0] = payload_version; PayloadId::new(out.as_slice()[..8].try_into().expect("sufficient length")) @@ -473,6 +480,37 @@ mod tests { ); } + #[test] + fn test_payload_id_parity_op_geth_jovian() { + // + let expected = + PayloadId::new(FixedBytes::<8>::from_str("0x046c65ffc4d659ec").unwrap().into()); + let attrs = OpPayloadAttributes { + payload_attributes: PayloadAttributes { + timestamp: 1728933301, + prev_randao: b256!("0x9158595abbdab2c90635087619aa7042bbebe47642dfab3c9bfb934f6b082765"), + suggested_fee_recipient: address!("0x4200000000000000000000000000000000000011"), + withdrawals: Some([].into()), + parent_beacon_block_root: b256!("0x8fe0193b9bf83cb7e5a08538e494fecc23046aab9a497af3704f4afdae3250ff").into(), + }, + transactions: Some([bytes!("7ef8f8a0dc19cfa777d90980e4875d0a548a881baaa3f83f14d1bc0d3038bc329350e54194deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8a4440a5e20000f424000000000000000000000000300000000670d6d890000000000000125000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000014bf9181db6e381d4384bbf69c48b0ee0eed23c6ca26143c6d2544f9d39997a590000000000000000000000007f83d659683caf2767fd3c720981d51f5bc365bc")].into()), + no_tx_pool: None, + gas_limit: Some(30000000), + eip_1559_params: None, + min_base_fee: Some(100), + }; + + // Reth's `PayloadId` should match op-geth's `PayloadId`. This fails + assert_eq!( + expected, + payload_id_optimism( + &b256!("0x3533bf30edaf9505d0810bf475cbe4e5f4b9889904b9845e83efdeab4e92eb1e"), + &attrs, + EngineApiMessageVersion::V4 as u8 + ) + ); + } + #[test] fn test_get_extra_data_post_holocene() { let attributes: OpPayloadBuilderAttributes = diff --git a/crates/prune/prune/Cargo.toml b/crates/prune/prune/Cargo.toml index 615a793bb89..a2d82c26923 100644 --- a/crates/prune/prune/Cargo.toml +++ b/crates/prune/prune/Cargo.toml @@ -24,6 +24,7 @@ reth-primitives-traits.workspace = true reth-static-file-types.workspace = true # ethereum +alloy-consensus.workspace = true alloy-eips.workspace = true # metrics diff --git a/crates/prune/prune/src/builder.rs b/crates/prune/prune/src/builder.rs index f61aa6bd46d..78283710e15 100644 --- a/crates/prune/prune/src/builder.rs +++ b/crates/prune/prune/src/builder.rs @@ -43,7 +43,7 @@ impl PrunerBuilder { } /// Sets the configuration for every part of the data that can be pruned. - pub const fn segments(mut self, segments: PruneModes) -> Self { + pub fn segments(mut self, segments: PruneModes) -> Self { self.segments = segments; self } diff --git a/crates/prune/prune/src/segments/mod.rs b/crates/prune/prune/src/segments/mod.rs index f4df3d2a0dd..f917c78ea94 100644 --- a/crates/prune/prune/src/segments/mod.rs +++ b/crates/prune/prune/src/segments/mod.rs @@ -10,8 +10,8 @@ pub use set::SegmentSet; use std::{fmt::Debug, ops::RangeInclusive}; use tracing::error; pub use user::{ - AccountHistory, Bodies, MerkleChangeSets, Receipts as UserReceipts, SenderRecovery, - StorageHistory, TransactionLookup, + AccountHistory, Bodies, MerkleChangeSets, Receipts as UserReceipts, ReceiptsByLogs, + SenderRecovery, StorageHistory, TransactionLookup, }; /// A segment represents a pruning of some portion of the data. diff --git a/crates/prune/prune/src/segments/set.rs b/crates/prune/prune/src/segments/set.rs index acd71f52e1b..7ae9e044e20 100644 --- a/crates/prune/prune/src/segments/set.rs +++ b/crates/prune/prune/src/segments/set.rs @@ -1,6 +1,6 @@ use crate::segments::{ - AccountHistory, Bodies, MerkleChangeSets, Segment, SenderRecovery, StorageHistory, - TransactionLookup, UserReceipts, + user::ReceiptsByLogs, AccountHistory, Bodies, MerkleChangeSets, Segment, SenderRecovery, + StorageHistory, TransactionLookup, UserReceipts, }; use alloy_eips::eip2718::Encodable2718; use reth_db_api::{table::Value, transaction::DbTxMut}; @@ -59,7 +59,6 @@ where _static_file_provider: StaticFileProvider, prune_modes: PruneModes, ) -> Self { - #[expect(deprecated)] let PruneModes { sender_recovery, transaction_lookup, @@ -68,7 +67,7 @@ where storage_history, bodies_history, merkle_changesets, - receipts_log_filter: (), + receipts_log_filter, } = prune_modes; Self::default() @@ -82,6 +81,11 @@ where .segment_opt(storage_history.map(StorageHistory::new)) // User receipts .segment_opt(receipts.map(UserReceipts::new)) + // Receipts by logs + .segment_opt( + (!receipts_log_filter.is_empty()) + .then(|| ReceiptsByLogs::new(receipts_log_filter.clone())), + ) // Transaction lookup .segment_opt(transaction_lookup.map(TransactionLookup::new)) // Sender recovery diff --git a/crates/prune/prune/src/segments/user/mod.rs b/crates/prune/prune/src/segments/user/mod.rs index ef7ae05a9d5..b993d3f2616 100644 --- a/crates/prune/prune/src/segments/user/mod.rs +++ b/crates/prune/prune/src/segments/user/mod.rs @@ -3,6 +3,7 @@ mod bodies; mod history; mod merkle_change_sets; mod receipts; +mod receipts_by_logs; mod sender_recovery; mod storage_history; mod transaction_lookup; @@ -11,6 +12,7 @@ pub use account_history::AccountHistory; pub use bodies::Bodies; pub use merkle_change_sets::MerkleChangeSets; pub use receipts::Receipts; +pub use receipts_by_logs::ReceiptsByLogs; pub use sender_recovery::SenderRecovery; pub use storage_history::StorageHistory; pub use transaction_lookup::TransactionLookup; diff --git a/crates/prune/prune/src/segments/user/receipts_by_logs.rs b/crates/prune/prune/src/segments/user/receipts_by_logs.rs new file mode 100644 index 00000000000..9e57bd2411a --- /dev/null +++ b/crates/prune/prune/src/segments/user/receipts_by_logs.rs @@ -0,0 +1,362 @@ +use crate::{ + db_ext::DbTxPruneExt, + segments::{PruneInput, Segment}, + PrunerError, +}; +use alloy_consensus::TxReceipt; +use reth_db_api::{table::Value, tables, transaction::DbTxMut}; +use reth_primitives_traits::NodePrimitives; +use reth_provider::{ + BlockReader, DBProvider, NodePrimitivesProvider, PruneCheckpointWriter, TransactionsProvider, +}; +use reth_prune_types::{ + PruneCheckpoint, PruneMode, PrunePurpose, PruneSegment, ReceiptsLogPruneConfig, SegmentOutput, + MINIMUM_PRUNING_DISTANCE, +}; +use tracing::{instrument, trace}; +#[derive(Debug)] +pub struct ReceiptsByLogs { + config: ReceiptsLogPruneConfig, +} + +impl ReceiptsByLogs { + pub const fn new(config: ReceiptsLogPruneConfig) -> Self { + Self { config } + } +} + +impl Segment for ReceiptsByLogs +where + Provider: DBProvider + + PruneCheckpointWriter + + TransactionsProvider + + BlockReader + + NodePrimitivesProvider>, +{ + fn segment(&self) -> PruneSegment { + PruneSegment::ContractLogs + } + + fn mode(&self) -> Option { + None + } + + fn purpose(&self) -> PrunePurpose { + PrunePurpose::User + } + + #[instrument(target = "pruner", skip(self, provider), ret(level = "trace"))] + fn prune(&self, provider: &Provider, input: PruneInput) -> Result { + // Contract log filtering removes every receipt possible except the ones in the list. So, + // for the other receipts it's as if they had a `PruneMode::Distance()` of + // `MINIMUM_PRUNING_DISTANCE`. + let to_block = PruneMode::Distance(MINIMUM_PRUNING_DISTANCE) + .prune_target_block(input.to_block, PruneSegment::ContractLogs, PrunePurpose::User)? + .map(|(bn, _)| bn) + .unwrap_or_default(); + + // Get status checkpoint from latest run + let mut last_pruned_block = + input.previous_checkpoint.and_then(|checkpoint| checkpoint.block_number); + + let initial_last_pruned_block = last_pruned_block; + + let mut from_tx_number = match initial_last_pruned_block { + Some(block) => provider + .block_body_indices(block)? + .map(|block| block.last_tx_num() + 1) + .unwrap_or(0), + None => 0, + }; + + // Figure out what receipts have already been pruned, so we can have an accurate + // `address_filter` + let address_filter = self.config.group_by_block(input.to_block, last_pruned_block)?; + + // Splits all transactions in different block ranges. Each block range will have its own + // filter address list and will check it while going through the table + // + // Example: + // For an `address_filter` such as: + // { block9: [a1, a2], block20: [a3, a4, a5] } + // + // The following structures will be created in the exact order as showed: + // `block_ranges`: [ + // (block0, block8, 0 addresses), + // (block9, block19, 2 addresses), + // (block20, to_block, 5 addresses) + // ] + // `filtered_addresses`: [a1, a2, a3, a4, a5] + // + // The first range will delete all receipts between block0 - block8 + // The second range will delete all receipts between block9 - 19, except the ones with + // emitter logs from these addresses: [a1, a2]. + // The third range will delete all receipts between block20 - to_block, except the ones with + // emitter logs from these addresses: [a1, a2, a3, a4, a5] + let mut block_ranges = vec![]; + let mut blocks_iter = address_filter.iter().peekable(); + let mut filtered_addresses = vec![]; + + while let Some((start_block, addresses)) = blocks_iter.next() { + filtered_addresses.extend_from_slice(addresses); + + // This will clear all receipts before the first appearance of a contract log or since + // the block after the last pruned one. + if block_ranges.is_empty() { + let init = last_pruned_block.map(|b| b + 1).unwrap_or_default(); + if init < *start_block { + block_ranges.push((init, *start_block - 1, 0)); + } + } + + let end_block = + blocks_iter.peek().map(|(next_block, _)| *next_block - 1).unwrap_or(to_block); + + // Addresses in lower block ranges, are still included in the inclusion list for future + // ranges. + block_ranges.push((*start_block, end_block, filtered_addresses.len())); + } + + trace!( + target: "pruner", + ?block_ranges, + ?filtered_addresses, + "Calculated block ranges and filtered addresses", + ); + + let mut limiter = input.limiter; + + let mut done = true; + let mut pruned = 0; + let mut last_pruned_transaction = None; + for (start_block, end_block, num_addresses) in block_ranges { + let block_range = start_block..=end_block; + + // Calculate the transaction range from this block range + let tx_range_end = match provider.block_body_indices(end_block)? { + Some(body) => body.last_tx_num(), + None => { + trace!( + target: "pruner", + ?block_range, + "No receipts to prune." + ); + continue + } + }; + let tx_range = from_tx_number..=tx_range_end; + + // Delete receipts, except the ones in the inclusion list + let mut last_skipped_transaction = 0; + let deleted; + (deleted, done) = provider.tx_ref().prune_table_with_range::::Receipt, + >>( + tx_range, + &mut limiter, + |(tx_num, receipt)| { + let skip = num_addresses > 0 && + receipt.logs().iter().any(|log| { + filtered_addresses[..num_addresses].contains(&&log.address) + }); + + if skip { + last_skipped_transaction = *tx_num; + } + skip + }, + |row| last_pruned_transaction = Some(row.0), + )?; + + trace!(target: "pruner", %deleted, %done, ?block_range, "Pruned receipts"); + + pruned += deleted; + + // For accurate checkpoints we need to know that we have checked every transaction. + // Example: we reached the end of the range, and the last receipt is supposed to skip + // its deletion. + let last_pruned_transaction = *last_pruned_transaction + .insert(last_pruned_transaction.unwrap_or_default().max(last_skipped_transaction)); + + last_pruned_block = Some( + provider + .block_by_transaction_id(last_pruned_transaction)? + .ok_or(PrunerError::InconsistentData("Block for transaction is not found"))? + // If there's more receipts to prune, set the checkpoint block number to + // previous, so we could finish pruning its receipts on the + // next run. + .saturating_sub(if done { 0 } else { 1 }), + ); + + if limiter.is_limit_reached() { + done &= end_block == to_block; + break + } + + from_tx_number = last_pruned_transaction + 1; + } + + // If there are contracts using `PruneMode::Distance(_)` there will be receipts before + // `to_block` that become eligible to be pruned in future runs. Therefore, our checkpoint is + // not actually `to_block`, but the `lowest_block_with_distance` from any contract. + // This ensures that in future pruner runs we can prune all these receipts between the + // previous `lowest_block_with_distance` and the new one using + // `get_next_tx_num_range_from_checkpoint`. + // + // Only applies if we were able to prune everything intended for this run, otherwise the + // checkpoint is the `last_pruned_block`. + let prune_mode_block = self + .config + .lowest_block_with_distance(input.to_block, initial_last_pruned_block)? + .unwrap_or(to_block); + + provider.save_prune_checkpoint( + PruneSegment::ContractLogs, + PruneCheckpoint { + block_number: Some(prune_mode_block.min(last_pruned_block.unwrap_or(u64::MAX))), + tx_number: last_pruned_transaction, + prune_mode: PruneMode::Before(prune_mode_block), + }, + )?; + + let progress = limiter.progress(done); + + Ok(SegmentOutput { progress, pruned, checkpoint: None }) + } +} + +#[cfg(test)] +mod tests { + use crate::segments::{user::ReceiptsByLogs, PruneInput, PruneLimiter, Segment}; + use alloy_primitives::B256; + use assert_matches::assert_matches; + use reth_db_api::{cursor::DbCursorRO, tables, transaction::DbTx}; + use reth_primitives_traits::InMemorySize; + use reth_provider::{BlockReader, DBProvider, DatabaseProviderFactory, PruneCheckpointReader}; + use reth_prune_types::{PruneMode, PruneSegment, ReceiptsLogPruneConfig}; + use reth_stages::test_utils::{StorageKind, TestStageDB}; + use reth_testing_utils::generators::{ + self, random_block_range, random_eoa_account, random_log, random_receipt, BlockRangeParams, + }; + use std::collections::BTreeMap; + + #[test] + fn prune_receipts_by_logs() { + reth_tracing::init_test_tracing(); + + let db = TestStageDB::default(); + let mut rng = generators::rng(); + + let tip = 20000; + let blocks = [ + random_block_range( + &mut rng, + 0..=100, + BlockRangeParams { parent: Some(B256::ZERO), tx_count: 1..5, ..Default::default() }, + ), + random_block_range( + &mut rng, + (100 + 1)..=(tip - 100), + BlockRangeParams { parent: Some(B256::ZERO), tx_count: 0..1, ..Default::default() }, + ), + random_block_range( + &mut rng, + (tip - 100 + 1)..=tip, + BlockRangeParams { parent: Some(B256::ZERO), tx_count: 1..5, ..Default::default() }, + ), + ] + .concat(); + db.insert_blocks(blocks.iter(), StorageKind::Database(None)).expect("insert blocks"); + + let mut receipts = Vec::new(); + + let (deposit_contract_addr, _) = random_eoa_account(&mut rng); + for block in &blocks { + receipts.reserve_exact(block.body().size()); + for (txi, transaction) in block.body().transactions.iter().enumerate() { + let mut receipt = random_receipt(&mut rng, transaction, Some(1), None); + receipt.logs.push(random_log( + &mut rng, + (txi == (block.transaction_count() - 1)).then_some(deposit_contract_addr), + Some(1), + )); + receipts.push((receipts.len() as u64, receipt)); + } + } + db.insert_receipts(receipts).expect("insert receipts"); + + assert_eq!( + db.table::().unwrap().len(), + blocks.iter().map(|block| block.transaction_count()).sum::() + ); + assert_eq!( + db.table::().unwrap().len(), + db.table::().unwrap().len() + ); + + let run_prune = || { + let provider = db.factory.database_provider_rw().unwrap(); + + let prune_before_block: usize = 20; + let prune_mode = PruneMode::Before(prune_before_block as u64); + let receipts_log_filter = + ReceiptsLogPruneConfig(BTreeMap::from([(deposit_contract_addr, prune_mode)])); + + let limiter = PruneLimiter::default().set_deleted_entries_limit(10); + + let result = ReceiptsByLogs::new(receipts_log_filter).prune( + &provider, + PruneInput { + previous_checkpoint: db + .factory + .provider() + .unwrap() + .get_prune_checkpoint(PruneSegment::ContractLogs) + .unwrap(), + to_block: tip, + limiter, + }, + ); + provider.commit().expect("commit"); + + assert_matches!(result, Ok(_)); + let output = result.unwrap(); + + let (pruned_block, pruned_tx) = db + .factory + .provider() + .unwrap() + .get_prune_checkpoint(PruneSegment::ContractLogs) + .unwrap() + .map(|checkpoint| (checkpoint.block_number.unwrap(), checkpoint.tx_number.unwrap())) + .unwrap_or_default(); + + // All receipts are in the end of the block + let unprunable = pruned_block.saturating_sub(prune_before_block as u64 - 1); + + assert_eq!( + db.table::().unwrap().len(), + blocks.iter().map(|block| block.transaction_count()).sum::() - + ((pruned_tx + 1) - unprunable) as usize + ); + + output.progress.is_finished() + }; + + while !run_prune() {} + + let provider = db.factory.provider().unwrap(); + let mut cursor = provider.tx_ref().cursor_read::().unwrap(); + let walker = cursor.walk(None).unwrap(); + for receipt in walker { + let (tx_num, receipt) = receipt.unwrap(); + + // Either we only find our contract, or the receipt is part of the unprunable receipts + // set by tip - 128 + assert!( + receipt.logs.iter().any(|l| l.address == deposit_contract_addr) || + provider.block_by_transaction_id(tx_num).unwrap().unwrap() > tip - 128, + ); + } + } +} diff --git a/crates/prune/types/src/lib.rs b/crates/prune/types/src/lib.rs index a588693892a..315063278b2 100644 --- a/crates/prune/types/src/lib.rs +++ b/crates/prune/types/src/lib.rs @@ -18,6 +18,10 @@ mod pruner; mod segment; mod target; +use alloc::{collections::BTreeMap, vec::Vec}; +use alloy_primitives::{Address, BlockNumber}; +use core::ops::Deref; + pub use checkpoint::PruneCheckpoint; pub use event::PrunerEvent; pub use mode::PruneMode; @@ -27,3 +31,300 @@ pub use pruner::{ }; pub use segment::{PrunePurpose, PruneSegment, PruneSegmentError}; pub use target::{PruneModes, UnwindTargetPrunedError, MINIMUM_PRUNING_DISTANCE}; + +/// Configuration for pruning receipts not associated with logs emitted by the specified contracts. +#[derive(Debug, Clone, PartialEq, Eq, Default)] +#[cfg_attr(any(test, feature = "serde"), derive(serde::Serialize, serde::Deserialize))] +pub struct ReceiptsLogPruneConfig(pub BTreeMap); + +impl ReceiptsLogPruneConfig { + /// Checks if the configuration is empty + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// Given the `tip` block number, consolidates the structure so it can easily be queried for + /// filtering across a range of blocks. + /// + /// Example: + /// + /// `{ addrA: Before(872), addrB: Before(500), addrC: Distance(128) }` + /// + /// for `tip: 1000`, gets transformed to a map such as: + /// + /// `{ 500: [addrB], 872: [addrA, addrC] }` + /// + /// The [`BlockNumber`] key of the new map should be viewed as `PruneMode::Before(block)`, which + /// makes the previous result equivalent to + /// + /// `{ Before(500): [addrB], Before(872): [addrA, addrC] }` + pub fn group_by_block( + &self, + tip: BlockNumber, + pruned_block: Option, + ) -> Result>, PruneSegmentError> { + let mut map = BTreeMap::new(); + let base_block = pruned_block.unwrap_or_default() + 1; + + for (address, mode) in &self.0 { + // Getting `None`, means that there is nothing to prune yet, so we need it to include in + // the BTreeMap (block = 0), otherwise it will be excluded. + // Reminder that this BTreeMap works as an inclusion list that excludes (prunes) all + // other receipts. + // + // Reminder, that we increment because the [`BlockNumber`] key of the new map should be + // viewed as `PruneMode::Before(block)` + let block = base_block.max( + mode.prune_target_block(tip, PruneSegment::ContractLogs, PrunePurpose::User)? + .map(|(block, _)| block) + .unwrap_or_default() + + 1, + ); + + map.entry(block).or_insert_with(Vec::new).push(address) + } + Ok(map) + } + + /// Returns the lowest block where we start filtering logs which use `PruneMode::Distance(_)`. + pub fn lowest_block_with_distance( + &self, + tip: BlockNumber, + pruned_block: Option, + ) -> Result, PruneSegmentError> { + let pruned_block = pruned_block.unwrap_or_default(); + let mut lowest = None; + + for mode in self.values() { + if mode.is_distance() && + let Some((block, _)) = + mode.prune_target_block(tip, PruneSegment::ContractLogs, PrunePurpose::User)? + { + lowest = Some(lowest.unwrap_or(u64::MAX).min(block)); + } + } + + Ok(lowest.map(|lowest| lowest.max(pruned_block))) + } +} + +impl Deref for ReceiptsLogPruneConfig { + type Target = BTreeMap; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_group_by_block_empty_config() { + let config = ReceiptsLogPruneConfig(BTreeMap::new()); + let tip = 1000; + let pruned_block = None; + + let result = config.group_by_block(tip, pruned_block).unwrap(); + assert!(result.is_empty(), "The result should be empty when the config is empty"); + } + + #[test] + fn test_group_by_block_single_entry() { + let mut config_map = BTreeMap::new(); + let address = Address::new([1; 20]); + let prune_mode = PruneMode::Before(500); + config_map.insert(address, prune_mode); + + let config = ReceiptsLogPruneConfig(config_map); + // Big tip to have something to prune for the target block + let tip = 3000000; + let pruned_block = Some(400); + + let result = config.group_by_block(tip, pruned_block).unwrap(); + + // Expect one entry with block 500 and the corresponding address + assert_eq!(result.len(), 1); + assert_eq!(result[&500], vec![&address], "Address should be grouped under block 500"); + + // Tip smaller than the target block, so that we have nothing to prune for the block + let tip = 300; + let pruned_block = Some(400); + + let result = config.group_by_block(tip, pruned_block).unwrap(); + + // Expect one entry with block 400 and the corresponding address + assert_eq!(result.len(), 1); + assert_eq!(result[&401], vec![&address], "Address should be grouped under block 400"); + } + + #[test] + fn test_group_by_block_multiple_entries() { + let mut config_map = BTreeMap::new(); + let address1 = Address::new([1; 20]); + let address2 = Address::new([2; 20]); + let prune_mode1 = PruneMode::Before(600); + let prune_mode2 = PruneMode::Before(800); + config_map.insert(address1, prune_mode1); + config_map.insert(address2, prune_mode2); + + let config = ReceiptsLogPruneConfig(config_map); + let tip = 900000; + let pruned_block = Some(400); + + let result = config.group_by_block(tip, pruned_block).unwrap(); + + // Expect two entries: one for block 600 and another for block 800 + assert_eq!(result.len(), 2); + assert_eq!(result[&600], vec![&address1], "Address1 should be grouped under block 600"); + assert_eq!(result[&800], vec![&address2], "Address2 should be grouped under block 800"); + } + + #[test] + fn test_group_by_block_with_distance_prune_mode() { + let mut config_map = BTreeMap::new(); + let address = Address::new([1; 20]); + let prune_mode = PruneMode::Distance(100000); + config_map.insert(address, prune_mode); + + let config = ReceiptsLogPruneConfig(config_map); + let tip = 100100; + // Pruned block is smaller than the target block + let pruned_block = Some(50); + + let result = config.group_by_block(tip, pruned_block).unwrap(); + + // Expect the entry to be grouped under block 100 (tip - distance) + assert_eq!(result.len(), 1); + assert_eq!(result[&101], vec![&address], "Address should be grouped under block 100"); + + let tip = 100100; + // Pruned block is larger than the target block + let pruned_block = Some(800); + + let result = config.group_by_block(tip, pruned_block).unwrap(); + + // Expect the entry to be grouped under block 800 which is larger than tip - distance + assert_eq!(result.len(), 1); + assert_eq!(result[&801], vec![&address], "Address should be grouped under block 800"); + } + + #[test] + fn test_lowest_block_with_distance_empty_config() { + let config = ReceiptsLogPruneConfig(BTreeMap::new()); + let tip = 1000; + let pruned_block = None; + + let result = config.lowest_block_with_distance(tip, pruned_block).unwrap(); + assert_eq!(result, None, "The result should be None when the config is empty"); + } + + #[test] + fn test_lowest_block_with_distance_no_distance_mode() { + let mut config_map = BTreeMap::new(); + let address = Address::new([1; 20]); + let prune_mode = PruneMode::Before(500); + config_map.insert(address, prune_mode); + + let config = ReceiptsLogPruneConfig(config_map); + let tip = 1000; + let pruned_block = None; + + let result = config.lowest_block_with_distance(tip, pruned_block).unwrap(); + assert_eq!(result, None, "The result should be None when there are no Distance modes"); + } + + #[test] + fn test_lowest_block_with_distance_single_entry() { + let mut config_map = BTreeMap::new(); + let address = Address::new([1; 20]); + let prune_mode = PruneMode::Distance(100000); + config_map.insert(address, prune_mode); + + let config = ReceiptsLogPruneConfig(config_map); + + let tip = 100100; + let pruned_block = Some(400); + + // Expect the lowest block to be 400 as 400 > 100100 - 100000 (tip - distance) + assert_eq!( + config.lowest_block_with_distance(tip, pruned_block).unwrap(), + Some(400), + "The lowest block should be 400" + ); + + let tip = 100100; + let pruned_block = Some(50); + + // Expect the lowest block to be 100 as 100 > 50 (pruned block) + assert_eq!( + config.lowest_block_with_distance(tip, pruned_block).unwrap(), + Some(100), + "The lowest block should be 100" + ); + } + + #[test] + fn test_lowest_block_with_distance_multiple_entries_last() { + let mut config_map = BTreeMap::new(); + let address1 = Address::new([1; 20]); + let address2 = Address::new([2; 20]); + let prune_mode1 = PruneMode::Distance(100100); + let prune_mode2 = PruneMode::Distance(100300); + config_map.insert(address1, prune_mode1); + config_map.insert(address2, prune_mode2); + + let config = ReceiptsLogPruneConfig(config_map); + let tip = 200300; + let pruned_block = Some(100); + + // The lowest block should be 200300 - 100300 = 100000: + // - First iteration will return 100200 => 200300 - 100100 = 100200 + // - Second iteration will return 100000 => 200300 - 100300 = 100000 < 100200 + // - Final result is 100000 + assert_eq!(config.lowest_block_with_distance(tip, pruned_block).unwrap(), Some(100000)); + } + + #[test] + fn test_lowest_block_with_distance_multiple_entries_first() { + let mut config_map = BTreeMap::new(); + let address1 = Address::new([1; 20]); + let address2 = Address::new([2; 20]); + let prune_mode1 = PruneMode::Distance(100400); + let prune_mode2 = PruneMode::Distance(100300); + config_map.insert(address1, prune_mode1); + config_map.insert(address2, prune_mode2); + + let config = ReceiptsLogPruneConfig(config_map); + let tip = 200300; + let pruned_block = Some(100); + + // The lowest block should be 200300 - 100400 = 99900: + // - First iteration, lowest block is 200300 - 100400 = 99900 + // - Second iteration, lowest block is still 99900 < 200300 - 100300 = 100000 + // - Final result is 99900 + assert_eq!(config.lowest_block_with_distance(tip, pruned_block).unwrap(), Some(99900)); + } + + #[test] + fn test_lowest_block_with_distance_multiple_entries_pruned_block() { + let mut config_map = BTreeMap::new(); + let address1 = Address::new([1; 20]); + let address2 = Address::new([2; 20]); + let prune_mode1 = PruneMode::Distance(100400); + let prune_mode2 = PruneMode::Distance(100300); + config_map.insert(address1, prune_mode1); + config_map.insert(address2, prune_mode2); + + let config = ReceiptsLogPruneConfig(config_map); + let tip = 200300; + let pruned_block = Some(100000); + + // The lowest block should be 100000 because: + // - Lowest is 200300 - 100400 = 99900 < 200300 - 100300 = 100000 + // - Lowest is compared to the pruned block 100000: 100000 > 99900 + // - Finally the lowest block is 100000 + assert_eq!(config.lowest_block_with_distance(tip, pruned_block).unwrap(), Some(100000)); + } +} diff --git a/crates/prune/types/src/target.rs b/crates/prune/types/src/target.rs index bb61c006cdc..3ff18554a9b 100644 --- a/crates/prune/types/src/target.rs +++ b/crates/prune/types/src/target.rs @@ -2,7 +2,7 @@ use alloy_primitives::BlockNumber; use derive_more::Display; use thiserror::Error; -use crate::{PruneCheckpoint, PruneMode, PruneSegment}; +use crate::{PruneCheckpoint, PruneMode, PruneSegment, ReceiptsLogPruneConfig}; /// Minimum distance from the tip necessary for the node to work correctly: /// 1. Minimum 2 epochs (32 blocks per epoch) required to handle any reorg according to the @@ -99,10 +99,16 @@ pub struct PruneModes { ) )] pub merkle_changesets: PruneMode, - /// Receipts log filtering has been deprecated and will be removed in a future release. - #[deprecated] - #[cfg_attr(any(test, feature = "serde"), serde(skip))] - pub receipts_log_filter: (), + /// Receipts pruning configuration by retaining only those receipts that contain logs emitted + /// by the specified addresses, discarding others. This setting is overridden by `receipts`. + /// + /// The [`BlockNumber`](`crate::BlockNumber`) represents the starting block from which point + /// onwards the receipts are preserved. + #[cfg_attr( + any(test, feature = "serde"), + serde(skip_serializing_if = "ReceiptsLogPruneConfig::is_empty") + )] + pub receipts_log_filter: ReceiptsLogPruneConfig, } impl Default for PruneModes { @@ -115,15 +121,14 @@ impl Default for PruneModes { storage_history: None, bodies_history: None, merkle_changesets: default_merkle_changesets_mode(), - #[expect(deprecated)] - receipts_log_filter: (), + receipts_log_filter: ReceiptsLogPruneConfig::default(), } } } impl PruneModes { /// Sets pruning to all targets. - pub const fn all() -> Self { + pub fn all() -> Self { Self { sender_recovery: Some(PruneMode::Full), transaction_lookup: Some(PruneMode::Full), @@ -132,14 +137,13 @@ impl PruneModes { storage_history: Some(PruneMode::Full), bodies_history: Some(PruneMode::Full), merkle_changesets: PruneMode::Full, - #[expect(deprecated)] - receipts_log_filter: (), + receipts_log_filter: Default::default(), } } /// Returns whether there is any kind of receipt pruning configuration. - pub const fn has_receipts_pruning(&self) -> bool { - self.receipts.is_some() + pub fn has_receipts_pruning(&self) -> bool { + self.receipts.is_some() || !self.receipts_log_filter.is_empty() } /// Returns an error if we can't unwind to the targeted block because the target block is diff --git a/crates/stages/stages/src/stages/execution.rs b/crates/stages/stages/src/stages/execution.rs index adfc87c5ccc..1666e79baf3 100644 --- a/crates/stages/stages/src/stages/execution.rs +++ b/crates/stages/stages/src/stages/execution.rs @@ -660,7 +660,7 @@ where mod tests { use super::*; use crate::{stages::MERKLE_STAGE_DEFAULT_REBUILD_THRESHOLD, test_utils::TestStageDB}; - use alloy_primitives::{address, hex_literal::hex, keccak256, B256, U256}; + use alloy_primitives::{address, hex_literal::hex, keccak256, Address, B256, U256}; use alloy_rlp::Decodable; use assert_matches::assert_matches; use reth_chainspec::ChainSpecBuilder; @@ -677,7 +677,9 @@ mod tests { DatabaseProviderFactory, ReceiptProvider, StaticFileProviderFactory, }; use reth_prune::PruneModes; + use reth_prune_types::{PruneMode, ReceiptsLogPruneConfig}; use reth_stages_api::StageUnitCheckpoint; + use std::collections::BTreeMap; fn stage() -> ExecutionStage { let evm_config = @@ -894,11 +896,20 @@ mod tests { // If there is a pruning configuration, then it's forced to use the database. // This way we test both cases. let modes = [None, Some(PruneModes::default())]; + let random_filter = ReceiptsLogPruneConfig(BTreeMap::from([( + Address::random(), + PruneMode::Distance(100000), + )])); // Tests node with database and node with static files - for mode in modes { + for mut mode in modes { let mut provider = factory.database_provider_rw().unwrap(); + if let Some(mode) = &mut mode { + // Simulating a full node where we write receipts to database + mode.receipts_log_filter = random_filter.clone(); + } + let mut execution_stage = stage(); provider.set_prune_modes(mode.clone().unwrap_or_default()); @@ -1022,9 +1033,18 @@ mod tests { // If there is a pruning configuration, then it's forced to use the database. // This way we test both cases. let modes = [None, Some(PruneModes::default())]; + let random_filter = ReceiptsLogPruneConfig(BTreeMap::from([( + Address::random(), + PruneMode::Before(100000), + )])); // Tests node with database and node with static files - for mode in modes { + for mut mode in modes { + if let Some(mode) = &mut mode { + // Simulating a full node where we write receipts to database + mode.receipts_log_filter = random_filter.clone(); + } + // Test Execution let mut execution_stage = stage(); provider.set_prune_modes(mode.clone().unwrap_or_default()); diff --git a/crates/static-file/static-file/src/static_file_producer.rs b/crates/static-file/static-file/src/static_file_producer.rs index 2e7aa4b9df4..03337f1fd7d 100644 --- a/crates/static-file/static-file/src/static_file_producer.rs +++ b/crates/static-file/static-file/src/static_file_producer.rs @@ -194,7 +194,9 @@ where let targets = StaticFileTargets { // StaticFile receipts only if they're not pruned according to the user configuration - receipts: if self.prune_modes.receipts.is_none() { + receipts: if self.prune_modes.receipts.is_none() && + self.prune_modes.receipts_log_filter.is_empty() + { finalized_block_numbers.receipts.and_then(|finalized_block_number| { self.get_static_file_target( highest_static_files.receipts, diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index 5d3b5280cda..873b10b0cfc 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -96,7 +96,7 @@ impl ProviderFactory { } /// Sets the pruning configuration for an existing [`ProviderFactory`]. - pub const fn with_prune_modes(mut self, prune_modes: PruneModes) -> Self { + pub fn with_prune_modes(mut self, prune_modes: PruneModes) -> Self { self.prune_modes = prune_modes; self } diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index a90b2c2e640..1f0a0aa391a 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -22,7 +22,7 @@ use crate::{ }; use alloy_consensus::{ transaction::{SignerRecoverable, TransactionMeta, TxHashRef}, - BlockHeader, + BlockHeader, TxReceipt, }; use alloy_eips::BlockHashOrNumber; use alloy_primitives::{ @@ -214,7 +214,7 @@ impl DatabaseProvider { #[cfg(feature = "test-utils")] /// Sets the prune modes for provider. - pub const fn set_prune_modes(&mut self, prune_modes: PruneModes) { + pub fn set_prune_modes(&mut self, prune_modes: PruneModes) { self.prune_modes = prune_modes; } } @@ -1621,11 +1621,20 @@ impl StateWriter .then(|| self.static_file_provider.get_writer(first_block, StaticFileSegment::Receipts)) .transpose()?; + let has_contract_log_filter = !self.prune_modes.receipts_log_filter.is_empty(); + let contract_log_pruner = self.prune_modes.receipts_log_filter.group_by_block(tip, None)?; + // All receipts from the last 128 blocks are required for blockchain tree, even with // [`PruneSegment::ContractLogs`]. let prunable_receipts = PruneMode::Distance(MINIMUM_PRUNING_DISTANCE).should_prune(first_block, tip); + // Prepare set of addresses which logs should not be pruned. + let mut allowed_addresses: HashSet = HashSet::new(); + for (_, addresses) in contract_log_pruner.range(..first_block) { + allowed_addresses.extend(addresses.iter().copied()); + } + for (idx, (receipts, first_tx_index)) in execution_outcome.receipts.iter().zip(block_indices).enumerate() { @@ -1645,8 +1654,21 @@ impl StateWriter continue } + // If there are new addresses to retain after this block number, track them + if let Some(new_addresses) = contract_log_pruner.get(&block_number) { + allowed_addresses.extend(new_addresses.iter().copied()); + } + for (idx, receipt) in receipts.iter().enumerate() { let receipt_idx = first_tx_index + idx as u64; + // Skip writing receipt if log filter is active and it does not have any logs to + // retain + if prunable_receipts && + has_contract_log_filter && + !receipt.logs().iter().any(|log| allowed_addresses.contains(&log.address)) + { + continue + } if let Some(writer) = &mut receipts_static_writer { writer.append_receipt(receipt_idx, receipt)?; diff --git a/docs/vocs/docs/pages/cli/reth/node.mdx b/docs/vocs/docs/pages/cli/reth/node.mdx index 2326b40d7fc..d92bad0c53d 100644 --- a/docs/vocs/docs/pages/cli/reth/node.mdx +++ b/docs/vocs/docs/pages/cli/reth/node.mdx @@ -801,6 +801,9 @@ Pruning: --prune.receipts.before Prune receipts before the specified block number. The specified block number is not pruned + --prune.receiptslogfilter + Configure receipts log filter. Format: <`address`>:<`prune_mode`>... where <`prune_mode`> can be 'full', 'distance:<`blocks`>', or 'before:<`block_number`>' + --prune.account-history.full Prunes all account history diff --git a/docs/vocs/vocs.config.ts b/docs/vocs/vocs.config.ts index 4deb6c6df0b..8664eedd3bf 100644 --- a/docs/vocs/vocs.config.ts +++ b/docs/vocs/vocs.config.ts @@ -21,7 +21,7 @@ export default defineConfig({ }, { text: 'GitHub', link: 'https://github.com/paradigmxyz/reth' }, { - text: 'v1.9.0', + text: 'v1.9.3', items: [ { text: 'Releases',