Merge branch 'unstable' into merge-unstable-to-deneb-20231005
# Conflicts: # .github/workflows/test-suite.yml # Cargo.lock # beacon_node/execution_layer/Cargo.toml # beacon_node/execution_layer/src/test_utils/mock_builder.rs # beacon_node/execution_layer/src/test_utils/mod.rs # beacon_node/network/src/service/tests.rs # consensus/types/src/builder_bid.rs
This commit is contained in:
commit
c5c84f1213
113
.config/nextest.toml
Normal file
113
.config/nextest.toml
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
# This is the default config used by nextest. It is embedded in the binary at
|
||||||
|
# build time. It may be used as a template for .config/nextest.toml.
|
||||||
|
|
||||||
|
[store]
|
||||||
|
# The directory under the workspace root at which nextest-related files are
|
||||||
|
# written. Profile-specific storage is currently written to dir/<profile-name>.
|
||||||
|
dir = "target/nextest"
|
||||||
|
|
||||||
|
# This section defines the default nextest profile. Custom profiles are layered
|
||||||
|
# on top of the default profile.
|
||||||
|
[profile.default]
|
||||||
|
# "retries" defines the number of times a test should be retried. If set to a
|
||||||
|
# non-zero value, tests that succeed on a subsequent attempt will be marked as
|
||||||
|
# non-flaky. Can be overridden through the `--retries` option.
|
||||||
|
# Examples
|
||||||
|
# * retries = 3
|
||||||
|
# * retries = { backoff = "fixed", count = 2, delay = "1s" }
|
||||||
|
# * retries = { backoff = "exponential", count = 10, delay = "1s", jitter = true, max-delay = "10s" }
|
||||||
|
retries = 0
|
||||||
|
|
||||||
|
# The number of threads to run tests with. Supported values are either an integer or
|
||||||
|
# the string "num-cpus". Can be overridden through the `--test-threads` option.
|
||||||
|
test-threads = "num-cpus"
|
||||||
|
|
||||||
|
# The number of threads required for each test. This is generally used in overrides to
|
||||||
|
# mark certain tests as heavier than others. However, it can also be set as a global parameter.
|
||||||
|
threads-required = 1
|
||||||
|
|
||||||
|
# Show these test statuses in the output.
|
||||||
|
#
|
||||||
|
# The possible values this can take are:
|
||||||
|
# * none: no output
|
||||||
|
# * fail: show failed (including exec-failed) tests
|
||||||
|
# * retry: show flaky and retried tests
|
||||||
|
# * slow: show slow tests
|
||||||
|
# * pass: show passed tests
|
||||||
|
# * skip: show skipped tests (most useful for CI)
|
||||||
|
# * all: all of the above
|
||||||
|
#
|
||||||
|
# Each value includes all the values above it; for example, "slow" includes
|
||||||
|
# failed and retried tests.
|
||||||
|
#
|
||||||
|
# Can be overridden through the `--status-level` flag.
|
||||||
|
status-level = "pass"
|
||||||
|
|
||||||
|
# Similar to status-level, show these test statuses at the end of the run.
|
||||||
|
final-status-level = "flaky"
|
||||||
|
|
||||||
|
# "failure-output" defines when standard output and standard error for failing tests are produced.
|
||||||
|
# Accepted values are
|
||||||
|
# * "immediate": output failures as soon as they happen
|
||||||
|
# * "final": output failures at the end of the test run
|
||||||
|
# * "immediate-final": output failures as soon as they happen and at the end of
|
||||||
|
# the test run; combination of "immediate" and "final"
|
||||||
|
# * "never": don't output failures at all
|
||||||
|
#
|
||||||
|
# For large test suites and CI it is generally useful to use "immediate-final".
|
||||||
|
#
|
||||||
|
# Can be overridden through the `--failure-output` option.
|
||||||
|
failure-output = "immediate"
|
||||||
|
|
||||||
|
# "success-output" controls production of standard output and standard error on success. This should
|
||||||
|
# generally be set to "never".
|
||||||
|
success-output = "never"
|
||||||
|
|
||||||
|
# Cancel the test run on the first failure. For CI runs, consider setting this
|
||||||
|
# to false.
|
||||||
|
fail-fast = true
|
||||||
|
|
||||||
|
# Treat a test that takes longer than the configured 'period' as slow, and print a message.
|
||||||
|
# See <https://nexte.st/book/slow-tests> for more information.
|
||||||
|
#
|
||||||
|
# Optional: specify the parameter 'terminate-after' with a non-zero integer,
|
||||||
|
# which will cause slow tests to be terminated after the specified number of
|
||||||
|
# periods have passed.
|
||||||
|
# Example: slow-timeout = { period = "60s", terminate-after = 2 }
|
||||||
|
slow-timeout = { period = "120s" }
|
||||||
|
|
||||||
|
# Treat a test as leaky if after the process is shut down, standard output and standard error
|
||||||
|
# aren't closed within this duration.
|
||||||
|
#
|
||||||
|
# This usually happens in case of a test that creates a child process and lets it inherit those
|
||||||
|
# handles, but doesn't clean the child process up (especially when it fails).
|
||||||
|
#
|
||||||
|
# See <https://nexte.st/book/leaky-tests> for more information.
|
||||||
|
leak-timeout = "100ms"
|
||||||
|
|
||||||
|
[profile.default.junit]
|
||||||
|
# Output a JUnit report into the given file inside 'store.dir/<profile-name>'.
|
||||||
|
# If unspecified, JUnit is not written out.
|
||||||
|
|
||||||
|
# path = "junit.xml"
|
||||||
|
|
||||||
|
# The name of the top-level "report" element in JUnit report. If aggregating
|
||||||
|
# reports across different test runs, it may be useful to provide separate names
|
||||||
|
# for each report.
|
||||||
|
report-name = "lighthouse-run"
|
||||||
|
|
||||||
|
# Whether standard output and standard error for passing tests should be stored in the JUnit report.
|
||||||
|
# Output is stored in the <system-out> and <system-err> elements of the <testcase> element.
|
||||||
|
store-success-output = false
|
||||||
|
|
||||||
|
# Whether standard output and standard error for failing tests should be stored in the JUnit report.
|
||||||
|
# Output is stored in the <system-out> and <system-err> elements of the <testcase> element.
|
||||||
|
#
|
||||||
|
# Note that if a description can be extracted from the output, it is always stored in the
|
||||||
|
# <description> element.
|
||||||
|
store-failure-output = true
|
||||||
|
|
||||||
|
# This profile is activated if MIRI_SYSROOT is set.
|
||||||
|
[profile.default-miri]
|
||||||
|
# Miri tests take up a lot of memory, so only run 1 test at a time by default.
|
||||||
|
test-threads = 4
|
296
.github/workflows/test-suite.yml
vendored
296
.github/workflows/test-suite.yml
vendored
@ -18,14 +18,14 @@ env:
|
|||||||
# Deny warnings in CI
|
# Deny warnings in CI
|
||||||
# Disable debug info (see https://github.com/sigp/lighthouse/issues/4005)
|
# Disable debug info (see https://github.com/sigp/lighthouse/issues/4005)
|
||||||
RUSTFLAGS: "-D warnings -C debuginfo=0"
|
RUSTFLAGS: "-D warnings -C debuginfo=0"
|
||||||
# The Nightly version used for cargo-udeps, might need updating from time to time.
|
|
||||||
PINNED_NIGHTLY: nightly-2023-04-16
|
|
||||||
# Prevent Github API rate limiting.
|
# Prevent Github API rate limiting.
|
||||||
LIGHTHOUSE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
LIGHTHOUSE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
# Enable self-hosted runners for the sigp repo only.
|
# Enable self-hosted runners for the sigp repo only.
|
||||||
SELF_HOSTED_RUNNERS: ${{ github.repository == 'sigp/lighthouse' }}
|
SELF_HOSTED_RUNNERS: ${{ github.repository == 'sigp/lighthouse' }}
|
||||||
# Self-hosted runners need to reference a different host for `./watch` tests.
|
# Self-hosted runners need to reference a different host for `./watch` tests.
|
||||||
WATCH_HOST: ${{ github.repository == 'sigp/lighthouse' && 'host.docker.internal' || 'localhost' }}
|
WATCH_HOST: ${{ github.repository == 'sigp/lighthouse' && 'host.docker.internal' || 'localhost' }}
|
||||||
|
# Disable incremental compilation
|
||||||
|
CARGO_INCREMENTAL: 0
|
||||||
jobs:
|
jobs:
|
||||||
target-branch-check:
|
target-branch-check:
|
||||||
name: target-branch-check
|
name: target-branch-check
|
||||||
@ -34,155 +34,191 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Check that the pull request is not targeting the stable branch
|
- name: Check that the pull request is not targeting the stable branch
|
||||||
run: test ${{ github.base_ref }} != "stable"
|
run: test ${{ github.base_ref }} != "stable"
|
||||||
extract-msrv:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Extract Minimum Supported Rust Version (MSRV)
|
|
||||||
run: |
|
|
||||||
metadata=$(cargo metadata --no-deps --format-version 1)
|
|
||||||
msrv=$(echo $metadata | jq -r '.packages | map(select(.name == "lighthouse")) | .[0].rust_version')
|
|
||||||
echo "MSRV=$msrv" >> $GITHUB_OUTPUT
|
|
||||||
id: extract_msrv
|
|
||||||
outputs:
|
|
||||||
MSRV: ${{ steps.extract_msrv.outputs.MSRV }}
|
|
||||||
cargo-fmt:
|
|
||||||
name: cargo-fmt
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Get latest version of stable Rust
|
|
||||||
run: rustup update stable
|
|
||||||
- name: Check formatting with cargo fmt
|
|
||||||
run: make cargo-fmt
|
|
||||||
release-tests-ubuntu:
|
release-tests-ubuntu:
|
||||||
name: release-tests-ubuntu
|
name: release-tests-ubuntu
|
||||||
# Use self-hosted runners only on the sigp repo.
|
# Use self-hosted runners only on the sigp repo.
|
||||||
runs-on: ${{ github.repository == 'sigp/lighthouse' && fromJson('["self-hosted", "linux", "CI", "large"]') || 'ubuntu-latest' }}
|
runs-on: ${{ github.repository == 'sigp/lighthouse' && fromJson('["self-hosted", "linux", "CI", "large"]') || 'ubuntu-latest' }}
|
||||||
needs: cargo-fmt
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Get latest version of stable Rust
|
- name: Get latest version of stable Rust
|
||||||
if: env.SELF_HOSTED_RUNNERS == false
|
if: env.SELF_HOSTED_RUNNERS == 'false'
|
||||||
run: rustup update stable
|
uses: moonrepo/setup-rust@v1
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
cache-target: release
|
||||||
|
bins: cargo-nextest
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Install Foundry (anvil)
|
- name: Install Foundry (anvil)
|
||||||
|
if: env.SELF_HOSTED_RUNNERS == 'false'
|
||||||
uses: foundry-rs/foundry-toolchain@v1
|
uses: foundry-rs/foundry-toolchain@v1
|
||||||
with:
|
with:
|
||||||
version: nightly-ca67d15f4abd46394b324c50e21e66f306a1162d
|
version: nightly-ca67d15f4abd46394b324c50e21e66f306a1162d
|
||||||
- name: Run tests in release
|
- name: Run tests in release
|
||||||
run: make test-release
|
run: make nextest-release
|
||||||
|
- name: Show cache stats
|
||||||
|
if: env.SELF_HOSTED_RUNNERS == 'true'
|
||||||
|
run: sccache --show-stats
|
||||||
release-tests-windows:
|
release-tests-windows:
|
||||||
name: release-tests-windows
|
name: release-tests-windows
|
||||||
runs-on: ${{ github.repository == 'sigp/lighthouse' && fromJson('["self-hosted", "windows", "CI"]') || 'windows-2019' }}
|
runs-on: ${{ github.repository == 'sigp/lighthouse' && fromJson('["self-hosted", "windows", "CI"]') || 'windows-2019' }}
|
||||||
needs: cargo-fmt
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Get latest version of stable Rust
|
- name: Get latest version of stable Rust
|
||||||
if: env.SELF_HOSTED_RUNNERS == false
|
if: env.SELF_HOSTED_RUNNERS == 'false'
|
||||||
run: rustup update stable
|
uses: moonrepo/setup-rust@v1
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
cache-target: release
|
||||||
|
bins: cargo-nextest
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Install Foundry (anvil)
|
- name: Install Foundry (anvil)
|
||||||
|
if: env.SELF_HOSTED_RUNNERS == 'false'
|
||||||
uses: foundry-rs/foundry-toolchain@v1
|
uses: foundry-rs/foundry-toolchain@v1
|
||||||
with:
|
with:
|
||||||
version: nightly-ca67d15f4abd46394b324c50e21e66f306a1162d
|
version: nightly-ca67d15f4abd46394b324c50e21e66f306a1162d
|
||||||
- name: Install make
|
- name: Install make
|
||||||
|
if: env.SELF_HOSTED_RUNNERS == 'false'
|
||||||
run: choco install -y make
|
run: choco install -y make
|
||||||
- uses: KyleMayes/install-llvm-action@v1
|
# - uses: KyleMayes/install-llvm-action@v1
|
||||||
if: env.SELF_HOSTED_RUNNERS == false
|
# if: env.SELF_HOSTED_RUNNERS == 'false'
|
||||||
with:
|
# with:
|
||||||
version: "15.0"
|
# version: "15.0"
|
||||||
directory: ${{ runner.temp }}/llvm
|
# directory: ${{ runner.temp }}/llvm
|
||||||
- name: Set LIBCLANG_PATH
|
- name: Set LIBCLANG_PATH
|
||||||
run: echo "LIBCLANG_PATH=$((gcm clang).source -replace "clang.exe")" >> $env:GITHUB_ENV
|
run: echo "LIBCLANG_PATH=$((gcm clang).source -replace "clang.exe")" >> $env:GITHUB_ENV
|
||||||
- name: Run tests in release
|
- name: Run tests in release
|
||||||
run: make test-release
|
run: make nextest-release
|
||||||
|
- name: Show cache stats
|
||||||
|
if: env.SELF_HOSTED_RUNNERS == 'true'
|
||||||
|
run: sccache --show-stats
|
||||||
beacon-chain-tests:
|
beacon-chain-tests:
|
||||||
name: beacon-chain-tests
|
name: beacon-chain-tests
|
||||||
# Use self-hosted runners only on the sigp repo.
|
# Use self-hosted runners only on the sigp repo.
|
||||||
runs-on: ${{ github.repository == 'sigp/lighthouse' && fromJson('["self-hosted", "linux", "CI", "large"]') || 'ubuntu-latest' }}
|
runs-on: ${{ github.repository == 'sigp/lighthouse' && fromJson('["self-hosted", "linux", "CI", "large"]') || 'ubuntu-latest' }}
|
||||||
needs: cargo-fmt
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Get latest version of stable Rust
|
- name: Get latest version of stable Rust
|
||||||
if: env.SELF_HOSTED_RUNNERS == false
|
if: env.SELF_HOSTED_RUNNERS == 'false'
|
||||||
run: rustup update stable
|
uses: moonrepo/setup-rust@v1
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
cache-target: release
|
||||||
|
bins: cargo-nextest
|
||||||
- name: Run beacon_chain tests for all known forks
|
- name: Run beacon_chain tests for all known forks
|
||||||
run: make test-beacon-chain
|
run: make test-beacon-chain
|
||||||
|
- name: Show cache stats
|
||||||
|
if: env.SELF_HOSTED_RUNNERS == 'true'
|
||||||
|
run: sccache --show-stats
|
||||||
op-pool-tests:
|
op-pool-tests:
|
||||||
name: op-pool-tests
|
name: op-pool-tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: cargo-fmt
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Get latest version of stable Rust
|
- name: Get latest version of stable Rust
|
||||||
run: rustup update stable
|
uses: moonrepo/setup-rust@v1
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
cache-target: release
|
||||||
|
bins: cargo-nextest
|
||||||
- name: Run operation_pool tests for all known forks
|
- name: Run operation_pool tests for all known forks
|
||||||
run: make test-op-pool
|
run: make test-op-pool
|
||||||
network-tests:
|
network-tests:
|
||||||
name: network-tests
|
name: network-tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: cargo-fmt
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Get latest version of stable Rust
|
- name: Get latest version of stable Rust
|
||||||
run: rustup update stable
|
uses: moonrepo/setup-rust@v1
|
||||||
- name: Run network tests for all known forks
|
with:
|
||||||
|
channel: stable
|
||||||
|
cache-target: release
|
||||||
|
bins: cargo-nextest
|
||||||
|
- name: Run network tests for all known forks
|
||||||
run: make test-network
|
run: make test-network
|
||||||
slasher-tests:
|
slasher-tests:
|
||||||
name: slasher-tests
|
name: slasher-tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: cargo-fmt
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Get latest version of stable Rust
|
- name: Get latest version of stable Rust
|
||||||
run: rustup update stable
|
uses: moonrepo/setup-rust@v1
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
cache-target: release
|
||||||
|
bins: cargo-nextest
|
||||||
- name: Run slasher tests for all supported backends
|
- name: Run slasher tests for all supported backends
|
||||||
run: make test-slasher
|
run: make test-slasher
|
||||||
debug-tests-ubuntu:
|
debug-tests-ubuntu:
|
||||||
name: debug-tests-ubuntu
|
name: debug-tests-ubuntu
|
||||||
# Use self-hosted runners only on the sigp repo.
|
# Use self-hosted runners only on the sigp repo.
|
||||||
runs-on: ${{ github.repository == 'sigp/lighthouse' && fromJson('["self-hosted", "linux", "CI", "large"]') || 'ubuntu-latest' }}
|
runs-on: ${{ github.repository == 'sigp/lighthouse' && fromJson('["self-hosted", "linux", "CI", "large"]') || 'ubuntu-latest' }}
|
||||||
needs: cargo-fmt
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Get latest version of stable Rust
|
- name: Get latest version of stable Rust
|
||||||
if: env.SELF_HOSTED_RUNNERS == false
|
if: env.SELF_HOSTED_RUNNERS == 'false'
|
||||||
run: rustup update stable
|
uses: moonrepo/setup-rust@v1
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
bins: cargo-nextest
|
||||||
- name: Install Foundry (anvil)
|
- name: Install Foundry (anvil)
|
||||||
|
if: env.SELF_HOSTED_RUNNERS == 'false'
|
||||||
uses: foundry-rs/foundry-toolchain@v1
|
uses: foundry-rs/foundry-toolchain@v1
|
||||||
with:
|
with:
|
||||||
version: nightly-ca67d15f4abd46394b324c50e21e66f306a1162d
|
version: nightly-ca67d15f4abd46394b324c50e21e66f306a1162d
|
||||||
- name: Run tests in debug
|
- name: Run tests in debug
|
||||||
run: make test-debug
|
run: make nextest-debug
|
||||||
|
- name: Show cache stats
|
||||||
|
if: env.SELF_HOSTED_RUNNERS == 'true'
|
||||||
|
run: sccache --show-stats
|
||||||
state-transition-vectors-ubuntu:
|
state-transition-vectors-ubuntu:
|
||||||
name: state-transition-vectors-ubuntu
|
name: state-transition-vectors-ubuntu
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: cargo-fmt
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Get latest version of stable Rust
|
- name: Get latest version of stable Rust
|
||||||
run: rustup update stable
|
uses: moonrepo/setup-rust@v1
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
cache-target: release
|
||||||
- name: Run state_transition_vectors in release.
|
- name: Run state_transition_vectors in release.
|
||||||
run: make run-state-transition-tests
|
run: make run-state-transition-tests
|
||||||
ef-tests-ubuntu:
|
ef-tests-ubuntu:
|
||||||
name: ef-tests-ubuntu
|
name: ef-tests-ubuntu
|
||||||
# Use self-hosted runners only on the sigp repo.
|
# Use self-hosted runners only on the sigp repo.
|
||||||
runs-on: ${{ github.repository == 'sigp/lighthouse' && fromJson('["self-hosted", "linux", "CI", "small"]') || 'ubuntu-latest' }}
|
runs-on: ${{ github.repository == 'sigp/lighthouse' && fromJson('["self-hosted", "linux", "CI", "small"]') || 'ubuntu-latest' }}
|
||||||
needs: cargo-fmt
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Get latest version of stable Rust
|
- name: Get latest version of stable Rust
|
||||||
if: env.SELF_HOSTED_RUNNERS == false
|
if: env.SELF_HOSTED_RUNNERS == 'false'
|
||||||
run: rustup update stable
|
uses: moonrepo/setup-rust@v1
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
cache-target: release
|
||||||
|
bins: cargo-nextest
|
||||||
- name: Run consensus-spec-tests with blst, milagro and fake_crypto
|
- name: Run consensus-spec-tests with blst, milagro and fake_crypto
|
||||||
run: make test-ef
|
run: make nextest-ef
|
||||||
|
- name: Show cache stats
|
||||||
|
if: env.SELF_HOSTED_RUNNERS == 'true'
|
||||||
|
run: sccache --show-stats
|
||||||
dockerfile-ubuntu:
|
dockerfile-ubuntu:
|
||||||
name: dockerfile-ubuntu
|
name: dockerfile-ubuntu
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: cargo-fmt
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Get latest version of stable Rust
|
|
||||||
run: rustup update stable
|
|
||||||
- name: Build the root Dockerfile
|
- name: Build the root Dockerfile
|
||||||
run: docker build --build-arg FEATURES=portable -t lighthouse:local .
|
run: docker build --build-arg FEATURES=portable -t lighthouse:local .
|
||||||
- name: Test the built image
|
- name: Test the built image
|
||||||
@ -190,11 +226,13 @@ jobs:
|
|||||||
eth1-simulator-ubuntu:
|
eth1-simulator-ubuntu:
|
||||||
name: eth1-simulator-ubuntu
|
name: eth1-simulator-ubuntu
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: cargo-fmt
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Get latest version of stable Rust
|
- name: Get latest version of stable Rust
|
||||||
run: rustup update stable
|
uses: moonrepo/setup-rust@v1
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
cache-target: release
|
||||||
- name: Install Foundry (anvil)
|
- name: Install Foundry (anvil)
|
||||||
uses: foundry-rs/foundry-toolchain@v1
|
uses: foundry-rs/foundry-toolchain@v1
|
||||||
with:
|
with:
|
||||||
@ -204,11 +242,13 @@ jobs:
|
|||||||
merge-transition-ubuntu:
|
merge-transition-ubuntu:
|
||||||
name: merge-transition-ubuntu
|
name: merge-transition-ubuntu
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: cargo-fmt
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Get latest version of stable Rust
|
- name: Get latest version of stable Rust
|
||||||
run: rustup update stable
|
uses: moonrepo/setup-rust@v1
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
cache-target: release
|
||||||
- name: Install Foundry (anvil)
|
- name: Install Foundry (anvil)
|
||||||
uses: foundry-rs/foundry-toolchain@v1
|
uses: foundry-rs/foundry-toolchain@v1
|
||||||
with:
|
with:
|
||||||
@ -218,21 +258,25 @@ jobs:
|
|||||||
no-eth1-simulator-ubuntu:
|
no-eth1-simulator-ubuntu:
|
||||||
name: no-eth1-simulator-ubuntu
|
name: no-eth1-simulator-ubuntu
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: cargo-fmt
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Get latest version of stable Rust
|
- name: Get latest version of stable Rust
|
||||||
run: rustup update stable
|
uses: moonrepo/setup-rust@v1
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
cache-target: release
|
||||||
- name: Run the beacon chain sim without an eth1 connection
|
- name: Run the beacon chain sim without an eth1 connection
|
||||||
run: cargo run --release --bin simulator no-eth1-sim
|
run: cargo run --release --bin simulator no-eth1-sim
|
||||||
syncing-simulator-ubuntu:
|
syncing-simulator-ubuntu:
|
||||||
name: syncing-simulator-ubuntu
|
name: syncing-simulator-ubuntu
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: cargo-fmt
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Get latest version of stable Rust
|
- name: Get latest version of stable Rust
|
||||||
run: rustup update stable
|
uses: moonrepo/setup-rust@v1
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
cache-target: release
|
||||||
- name: Install Foundry (anvil)
|
- name: Install Foundry (anvil)
|
||||||
uses: foundry-rs/foundry-toolchain@v1
|
uses: foundry-rs/foundry-toolchain@v1
|
||||||
with:
|
with:
|
||||||
@ -241,21 +285,27 @@ jobs:
|
|||||||
run: cargo run --release --bin simulator syncing-sim
|
run: cargo run --release --bin simulator syncing-sim
|
||||||
doppelganger-protection-test:
|
doppelganger-protection-test:
|
||||||
name: doppelganger-protection-test
|
name: doppelganger-protection-test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ github.repository == 'sigp/lighthouse' && fromJson('["self-hosted", "linux", "CI", "small"]') || 'ubuntu-latest' }}
|
||||||
needs: cargo-fmt
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Get latest version of stable Rust
|
- name: Get latest version of stable Rust
|
||||||
run: rustup update stable
|
if: env.SELF_HOSTED_RUNNERS == 'false'
|
||||||
|
uses: moonrepo/setup-rust@v1
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
cache-target: release
|
||||||
- name: Install geth
|
- name: Install geth
|
||||||
|
if: env.SELF_HOSTED_RUNNERS == 'false'
|
||||||
run: |
|
run: |
|
||||||
sudo add-apt-repository -y ppa:ethereum/ethereum
|
sudo add-apt-repository -y ppa:ethereum/ethereum
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install ethereum
|
sudo apt-get install ethereum
|
||||||
- name: Install lighthouse and lcli
|
- name: Install lighthouse
|
||||||
run: |
|
run: |
|
||||||
make
|
make
|
||||||
make install-lcli
|
- name: Install lcli
|
||||||
|
if: env.SELF_HOSTED_RUNNERS == 'false'
|
||||||
|
run: make install-lcli
|
||||||
- name: Run the doppelganger protection failure test script
|
- name: Run the doppelganger protection failure test script
|
||||||
run: |
|
run: |
|
||||||
cd scripts/tests
|
cd scripts/tests
|
||||||
@ -267,91 +317,73 @@ jobs:
|
|||||||
execution-engine-integration-ubuntu:
|
execution-engine-integration-ubuntu:
|
||||||
name: execution-engine-integration-ubuntu
|
name: execution-engine-integration-ubuntu
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: cargo-fmt
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-go@v3
|
|
||||||
with:
|
|
||||||
go-version: '1.20'
|
|
||||||
- uses: actions/setup-dotnet@v3
|
|
||||||
with:
|
|
||||||
dotnet-version: '6.0.201'
|
|
||||||
- name: Get latest version of stable Rust
|
- name: Get latest version of stable Rust
|
||||||
run: rustup update stable
|
uses: moonrepo/setup-rust@v1
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
cache-target: release
|
||||||
|
cache: false
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Run exec engine integration tests in release
|
- name: Run exec engine integration tests in release
|
||||||
run: make test-exec-engine
|
run: make test-exec-engine
|
||||||
check-benchmarks:
|
check-code:
|
||||||
name: check-benchmarks
|
name: check-code
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: cargo-fmt
|
env:
|
||||||
|
CARGO_INCREMENTAL: 1
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Get latest version of stable Rust
|
- name: Get latest version of stable Rust
|
||||||
run: rustup update stable
|
uses: moonrepo/setup-rust@v1
|
||||||
- name: Typecheck benchmark code without running it
|
with:
|
||||||
run: make check-benches
|
channel: stable
|
||||||
clippy:
|
cache-target: release
|
||||||
name: clippy
|
components: rustfmt,clippy
|
||||||
runs-on: ubuntu-latest
|
bins: cargo-audit
|
||||||
needs: cargo-fmt
|
- name: Check formatting with cargo fmt
|
||||||
steps:
|
run: make cargo-fmt
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Get latest version of stable Rust
|
|
||||||
run: rustup update stable
|
|
||||||
- name: Lint code for quality and style with Clippy
|
- name: Lint code for quality and style with Clippy
|
||||||
run: make lint
|
run: make lint
|
||||||
- name: Certify Cargo.lock freshness
|
- name: Certify Cargo.lock freshness
|
||||||
run: git diff --exit-code Cargo.lock
|
run: git diff --exit-code Cargo.lock
|
||||||
|
- name: Typecheck benchmark code without running it
|
||||||
|
run: make check-benches
|
||||||
|
- name: Validate state_processing feature arbitrary-fuzz
|
||||||
|
run: make arbitrary-fuzz
|
||||||
|
- name: Run cargo audit
|
||||||
|
run: make audit-CI
|
||||||
|
# TODO(sean): re-enable this when we can figure it out with c-kzg
|
||||||
|
# Issue: https://github.com/sigp/lighthouse/issues/4440
|
||||||
|
# - name: Run cargo vendor to make sure dependencies can be vendored for packaging, reproducibility and archival purpose
|
||||||
|
# run: CARGO_HOME=$(readlink -f $HOME) make vendor
|
||||||
check-msrv:
|
check-msrv:
|
||||||
name: check-msrv
|
name: check-msrv
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [cargo-fmt, extract-msrv]
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Install Rust @ MSRV (${{ needs.extract-msrv.outputs.MSRV }})
|
- name: Install Rust at Minimum Supported Rust Version (MSRV)
|
||||||
run: rustup override set ${{ needs.extract-msrv.outputs.MSRV }}
|
run: |
|
||||||
|
metadata=$(cargo metadata --no-deps --format-version 1)
|
||||||
|
msrv=$(echo $metadata | jq -r '.packages | map(select(.name == "lighthouse")) | .[0].rust_version')
|
||||||
|
rustup override set $msrv
|
||||||
- name: Run cargo check
|
- name: Run cargo check
|
||||||
run: cargo check --workspace
|
run: cargo check --workspace
|
||||||
arbitrary-check:
|
|
||||||
name: arbitrary-check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: cargo-fmt
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Get latest version of stable Rust
|
|
||||||
run: rustup update stable
|
|
||||||
- name: Validate state_processing feature arbitrary-fuzz
|
|
||||||
run: make arbitrary-fuzz
|
|
||||||
cargo-audit:
|
|
||||||
name: cargo-audit
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: cargo-fmt
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Get latest version of stable Rust
|
|
||||||
run: rustup update stable
|
|
||||||
- name: Run cargo audit to identify known security vulnerabilities reported to the RustSec Advisory Database
|
|
||||||
run: make audit
|
|
||||||
# TODO(sean): re-enable this when we can figure it out with c-kzg
|
|
||||||
# Issue: https://github.com/sigp/lighthouse/issues/4440
|
|
||||||
# cargo-vendor:
|
|
||||||
# name: cargo-vendor
|
|
||||||
# runs-on: ubuntu-latest
|
|
||||||
# needs: cargo-fmt
|
|
||||||
# steps:
|
|
||||||
# - uses: actions/checkout@v3
|
|
||||||
# - name: Run cargo vendor to make sure dependencies can be vendored for packaging, reproducibility and archival purpose
|
|
||||||
# run: CARGO_HOME=$(readlink -f $HOME) make vendor
|
|
||||||
cargo-udeps:
|
cargo-udeps:
|
||||||
name: cargo-udeps
|
name: cargo-udeps
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: cargo-fmt
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Install Rust (${{ env.PINNED_NIGHTLY }})
|
- name: Get latest version of nightly Rust
|
||||||
run: rustup toolchain install $PINNED_NIGHTLY
|
uses: moonrepo/setup-rust@v1
|
||||||
- name: Install cargo-udeps
|
with:
|
||||||
run: cargo install cargo-udeps --locked --force
|
channel: nightly
|
||||||
|
bins: cargo-udeps
|
||||||
|
cache: false
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Create Cargo config dir
|
- name: Create Cargo config dir
|
||||||
run: mkdir -p .cargo
|
run: mkdir -p .cargo
|
||||||
- name: Install custom Cargo config
|
- name: Install custom Cargo config
|
||||||
|
587
Cargo.lock
generated
587
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -137,7 +137,7 @@ r2d2 = "0.8"
|
|||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
rayon = "1.7"
|
rayon = "1.7"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
reqwest = { version = "0.11", default-features = false, features = ["blocking", "json", "stream", "rustls-tls"] }
|
reqwest = { version = "0.11", default-features = false, features = ["blocking", "json", "stream", "rustls-tls", "native-tls-vendored"] }
|
||||||
ring = "0.16"
|
ring = "0.16"
|
||||||
rusqlite = { version = "0.28", features = ["bundled"] }
|
rusqlite = { version = "0.28", features = ["bundled"] }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
@ -157,7 +157,7 @@ superstruct = "0.6"
|
|||||||
syn = "1"
|
syn = "1"
|
||||||
sysinfo = "0.26"
|
sysinfo = "0.26"
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
tokio = { version = "1", features = ["rt-multi-thread", "sync"] }
|
tokio = { version = "1", features = ["rt-multi-thread", "sync", "signal"] }
|
||||||
tokio-stream = { version = "0.1", features = ["sync"] }
|
tokio-stream = { version = "0.1", features = ["sync"] }
|
||||||
tokio-util = { version = "0.6", features = ["codec", "compat", "time"] }
|
tokio-util = { version = "0.6", features = ["codec", "compat", "time"] }
|
||||||
tree_hash = "0.5"
|
tree_hash = "0.5"
|
||||||
|
39
Makefile
39
Makefile
@ -108,11 +108,21 @@ build-release-tarballs:
|
|||||||
test-release:
|
test-release:
|
||||||
cargo test --workspace --release --exclude ef_tests --exclude beacon_chain --exclude slasher --exclude network
|
cargo test --workspace --release --exclude ef_tests --exclude beacon_chain --exclude slasher --exclude network
|
||||||
|
|
||||||
|
# Runs the full workspace tests in **release**, without downloading any additional
|
||||||
|
# test vectors, using nextest.
|
||||||
|
nextest-release:
|
||||||
|
cargo nextest run --workspace --release --exclude ef_tests --exclude beacon_chain --exclude slasher
|
||||||
|
|
||||||
# Runs the full workspace tests in **debug**, without downloading any additional test
|
# Runs the full workspace tests in **debug**, without downloading any additional test
|
||||||
# vectors.
|
# vectors.
|
||||||
test-debug:
|
test-debug:
|
||||||
cargo test --workspace --exclude ef_tests --exclude beacon_chain --exclude network
|
cargo test --workspace --exclude ef_tests --exclude beacon_chain --exclude network
|
||||||
|
|
||||||
|
# Runs the full workspace tests in **debug**, without downloading any additional test
|
||||||
|
# vectors, using nextest.
|
||||||
|
nextest-debug:
|
||||||
|
cargo nextest run --workspace --exclude ef_tests --exclude beacon_chain
|
||||||
|
|
||||||
# Runs cargo-fmt (linter).
|
# Runs cargo-fmt (linter).
|
||||||
cargo-fmt:
|
cargo-fmt:
|
||||||
cargo fmt --all -- --check
|
cargo fmt --all -- --check
|
||||||
@ -129,17 +139,25 @@ run-ef-tests:
|
|||||||
cargo test --release -p ef_tests --features "ef_tests,$(EF_TEST_FEATURES),milagro"
|
cargo test --release -p ef_tests --features "ef_tests,$(EF_TEST_FEATURES),milagro"
|
||||||
./$(EF_TESTS)/check_all_files_accessed.py $(EF_TESTS)/.accessed_file_log.txt $(EF_TESTS)/consensus-spec-tests
|
./$(EF_TESTS)/check_all_files_accessed.py $(EF_TESTS)/.accessed_file_log.txt $(EF_TESTS)/consensus-spec-tests
|
||||||
|
|
||||||
|
# Runs EF test vectors with nextest
|
||||||
|
nextest-run-ef-tests:
|
||||||
|
rm -rf $(EF_TESTS)/.accessed_file_log.txt
|
||||||
|
cargo nextest run --release -p ef_tests --features "ef_tests,$(EF_TEST_FEATURES)"
|
||||||
|
cargo nextest run --release -p ef_tests --features "ef_tests,$(EF_TEST_FEATURES),fake_crypto"
|
||||||
|
cargo nextest run --release -p ef_tests --features "ef_tests,$(EF_TEST_FEATURES),milagro"
|
||||||
|
./$(EF_TESTS)/check_all_files_accessed.py $(EF_TESTS)/.accessed_file_log.txt $(EF_TESTS)/consensus-spec-tests
|
||||||
|
|
||||||
# Run the tests in the `beacon_chain` crate for all known forks.
|
# Run the tests in the `beacon_chain` crate for all known forks.
|
||||||
test-beacon-chain: $(patsubst %,test-beacon-chain-%,$(FORKS))
|
test-beacon-chain: $(patsubst %,test-beacon-chain-%,$(FORKS))
|
||||||
|
|
||||||
test-beacon-chain-%:
|
test-beacon-chain-%:
|
||||||
env FORK_NAME=$* cargo test --release --features fork_from_env,slasher/lmdb -p beacon_chain
|
env FORK_NAME=$* cargo nextest run --release --features fork_from_env,slasher/lmdb -p beacon_chain
|
||||||
|
|
||||||
# Run the tests in the `operation_pool` crate for all known forks.
|
# Run the tests in the `operation_pool` crate for all known forks.
|
||||||
test-op-pool: $(patsubst %,test-op-pool-%,$(FORKS))
|
test-op-pool: $(patsubst %,test-op-pool-%,$(FORKS))
|
||||||
|
|
||||||
test-op-pool-%:
|
test-op-pool-%:
|
||||||
env FORK_NAME=$* cargo test --release \
|
env FORK_NAME=$* cargo nextest run --release \
|
||||||
--features 'beacon_chain/fork_from_env'\
|
--features 'beacon_chain/fork_from_env'\
|
||||||
-p operation_pool
|
-p operation_pool
|
||||||
|
|
||||||
@ -147,15 +165,15 @@ test-op-pool-%:
|
|||||||
test-network: $(patsubst %,test-network-%,$(FORKS))
|
test-network: $(patsubst %,test-network-%,$(FORKS))
|
||||||
|
|
||||||
test-network-%:
|
test-network-%:
|
||||||
env FORK_NAME=$* cargo test --release \
|
env FORK_NAME=$* cargo nextest run --release \
|
||||||
--features 'fork_from_env' \
|
--features 'fork_from_env' \
|
||||||
-p network
|
-p network
|
||||||
|
|
||||||
# Run the tests in the `slasher` crate for all supported database backends.
|
# Run the tests in the `slasher` crate for all supported database backends.
|
||||||
test-slasher:
|
test-slasher:
|
||||||
cargo test --release -p slasher --features lmdb
|
cargo nextest run --release -p slasher --features lmdb
|
||||||
cargo test --release -p slasher --no-default-features --features mdbx
|
cargo nextest run --release -p slasher --no-default-features --features mdbx
|
||||||
cargo test --release -p slasher --features lmdb,mdbx # both backends enabled
|
cargo nextest run --release -p slasher --features lmdb,mdbx # both backends enabled
|
||||||
|
|
||||||
# Runs only the tests/state_transition_vectors tests.
|
# Runs only the tests/state_transition_vectors tests.
|
||||||
run-state-transition-tests:
|
run-state-transition-tests:
|
||||||
@ -164,6 +182,9 @@ run-state-transition-tests:
|
|||||||
# Downloads and runs the EF test vectors.
|
# Downloads and runs the EF test vectors.
|
||||||
test-ef: make-ef-tests run-ef-tests
|
test-ef: make-ef-tests run-ef-tests
|
||||||
|
|
||||||
|
# Downloads and runs the EF test vectors with nextest.
|
||||||
|
nextest-ef: make-ef-tests nextest-run-ef-tests
|
||||||
|
|
||||||
# Runs tests checking interop between Lighthouse and execution clients.
|
# Runs tests checking interop between Lighthouse and execution clients.
|
||||||
test-exec-engine:
|
test-exec-engine:
|
||||||
make -C $(EXECUTION_ENGINE_INTEGRATION) test
|
make -C $(EXECUTION_ENGINE_INTEGRATION) test
|
||||||
@ -213,8 +234,12 @@ arbitrary-fuzz:
|
|||||||
cargo check -p slashing_protection --features arbitrary-fuzz
|
cargo check -p slashing_protection --features arbitrary-fuzz
|
||||||
|
|
||||||
# Runs cargo audit (Audit Cargo.lock files for crates with security vulnerabilities reported to the RustSec Advisory Database)
|
# Runs cargo audit (Audit Cargo.lock files for crates with security vulnerabilities reported to the RustSec Advisory Database)
|
||||||
audit:
|
audit: install-audit audit-CI
|
||||||
|
|
||||||
|
install-audit:
|
||||||
cargo install --force cargo-audit
|
cargo install --force cargo-audit
|
||||||
|
|
||||||
|
audit-CI:
|
||||||
cargo audit
|
cargo audit
|
||||||
|
|
||||||
# Runs `cargo vendor` to make sure dependencies can be vendored for packaging, reproducibility and archival purpose.
|
# Runs `cargo vendor` to make sure dependencies can be vendored for packaging, reproducibility and archival purpose.
|
||||||
|
@ -20,8 +20,8 @@ use execution_layer::test_utils::generate_genesis_header;
|
|||||||
use execution_layer::{
|
use execution_layer::{
|
||||||
auth::JwtKey,
|
auth::JwtKey,
|
||||||
test_utils::{
|
test_utils::{
|
||||||
ExecutionBlockGenerator, MockBuilder, MockBuilderServer, MockExecutionLayer,
|
ExecutionBlockGenerator, MockBuilder, MockExecutionLayer, DEFAULT_JWT_SECRET,
|
||||||
DEFAULT_JWT_SECRET, DEFAULT_TERMINAL_BLOCK,
|
DEFAULT_TERMINAL_BLOCK,
|
||||||
},
|
},
|
||||||
ExecutionLayer,
|
ExecutionLayer,
|
||||||
};
|
};
|
||||||
@ -663,7 +663,10 @@ where
|
|||||||
.execution_block_generator()
|
.execution_block_generator()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_mock_builder(&mut self, beacon_url: SensitiveUrl) -> MockBuilderServer {
|
pub fn set_mock_builder(
|
||||||
|
&mut self,
|
||||||
|
beacon_url: SensitiveUrl,
|
||||||
|
) -> impl futures::Future<Output = ()> {
|
||||||
let mock_el = self
|
let mock_el = self
|
||||||
.mock_execution_layer
|
.mock_execution_layer
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -672,7 +675,7 @@ where
|
|||||||
let mock_el_url = SensitiveUrl::parse(mock_el.server.url().as_str()).unwrap();
|
let mock_el_url = SensitiveUrl::parse(mock_el.server.url().as_str()).unwrap();
|
||||||
|
|
||||||
// Create the builder, listening on a free port.
|
// Create the builder, listening on a free port.
|
||||||
let (mock_builder, mock_builder_server) = MockBuilder::new_for_testing(
|
let (mock_builder, (addr, mock_builder_server)) = MockBuilder::new_for_testing(
|
||||||
mock_el_url,
|
mock_el_url,
|
||||||
beacon_url,
|
beacon_url,
|
||||||
self.spec.clone(),
|
self.spec.clone(),
|
||||||
@ -680,8 +683,7 @@ where
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Set the builder URL in the execution layer now that its port is known.
|
// Set the builder URL in the execution layer now that its port is known.
|
||||||
let builder_listen_addr = mock_builder_server.local_addr();
|
let port = addr.port();
|
||||||
let port = builder_listen_addr.port();
|
|
||||||
mock_el
|
mock_el
|
||||||
.el
|
.el
|
||||||
.set_builder_url(
|
.set_builder_url(
|
||||||
|
@ -42,12 +42,6 @@ lazy_static = { workspace = true }
|
|||||||
ethers-core = { workspace = true }
|
ethers-core = { workspace = true }
|
||||||
builder_client = { path = "../builder_client" }
|
builder_client = { path = "../builder_client" }
|
||||||
fork_choice = { workspace = true }
|
fork_choice = { workspace = true }
|
||||||
#PR: https://github.com/ralexstokes/mev-rs/pull/124
|
|
||||||
mev-rs = { git = "https://github.com/jimmygchen/mev-rs", rev = "dedc77a" }
|
|
||||||
axum = "0.6"
|
|
||||||
hyper = "0.14"
|
|
||||||
ethereum-consensus = { git = "https://github.com/ralexstokes/ethereum-consensus", rev = "12508c1f9b0c8f4bf4c5e9b6d441e840c1b37fd9" }
|
|
||||||
ssz_rs = "0.9.0"
|
|
||||||
tokio-stream = { workspace = true }
|
tokio-stream = { workspace = true }
|
||||||
strum = { workspace = true }
|
strum = { workspace = true }
|
||||||
keccak-hash = "0.10.0"
|
keccak-hash = "0.10.0"
|
||||||
|
@ -1,51 +1,30 @@
|
|||||||
use crate::test_utils::{DEFAULT_BUILDER_PAYLOAD_VALUE_WEI, DEFAULT_JWT_SECRET};
|
use crate::test_utils::{DEFAULT_BUILDER_PAYLOAD_VALUE_WEI, DEFAULT_JWT_SECRET};
|
||||||
use crate::{Config, ExecutionLayer, PayloadAttributes};
|
use crate::{Config, ExecutionLayer, PayloadAttributes};
|
||||||
use async_trait::async_trait;
|
|
||||||
use eth2::types::{BlobsBundle, BlockId, StateId, ValidatorId};
|
use eth2::types::{BlobsBundle, BlockId, StateId, ValidatorId};
|
||||||
use eth2::{BeaconNodeHttpClient, Timeouts};
|
use eth2::{BeaconNodeHttpClient, Timeouts};
|
||||||
pub use ethereum_consensus::state_transition::Context;
|
|
||||||
use ethereum_consensus::{
|
|
||||||
crypto::{SecretKey, Signature},
|
|
||||||
primitives::{BlsPublicKey, BlsSignature, ExecutionAddress, Hash32, Root, U256},
|
|
||||||
state_transition::Error,
|
|
||||||
};
|
|
||||||
use fork_choice::ForkchoiceUpdateParameters;
|
use fork_choice::ForkchoiceUpdateParameters;
|
||||||
use mev_rs::{
|
|
||||||
blinded_block_provider::Server as BlindedBlockProviderServer,
|
|
||||||
signing::{sign_builder_message, verify_signed_builder_message},
|
|
||||||
types::{
|
|
||||||
bellatrix::{
|
|
||||||
BuilderBid as BuilderBidBellatrix, SignedBuilderBid as SignedBuilderBidBellatrix,
|
|
||||||
},
|
|
||||||
capella::{BuilderBid as BuilderBidCapella, SignedBuilderBid as SignedBuilderBidCapella},
|
|
||||||
deneb::{BuilderBid as BuilderBidDeneb, SignedBuilderBid as SignedBuilderBidDeneb},
|
|
||||||
BidRequest, BuilderBid, ExecutionPayload as ServerPayload, SignedBlindedBeaconBlock,
|
|
||||||
SignedBuilderBid, SignedValidatorRegistration,
|
|
||||||
},
|
|
||||||
Error as MevError,
|
|
||||||
};
|
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use sensitive_url::SensitiveUrl;
|
use sensitive_url::SensitiveUrl;
|
||||||
use ssz::{Decode, Encode};
|
|
||||||
use ssz_rs::{Merkleized, SimpleSerialize};
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::net::Ipv4Addr;
|
use std::future::Future;
|
||||||
|
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use task_executor::TaskExecutor;
|
use task_executor::TaskExecutor;
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
use tree_hash::TreeHash;
|
use tree_hash::TreeHash;
|
||||||
use types::builder_bid::BlindedBlobsBundle;
|
use types::builder_bid::{
|
||||||
|
BuilderBid, BuilderBidCapella, BuilderBidDeneb, BuilderBidMerge, SignedBuilderBid,
|
||||||
|
};
|
||||||
use types::{
|
use types::{
|
||||||
Address, BeaconState, ChainSpec, EthSpec, ExecPayload, ExecutionPayload,
|
Address, BeaconState, ChainSpec, EthSpec, ExecPayload, ExecutionPayload,
|
||||||
ExecutionPayloadHeader, ForkName, ForkVersionedResponse, Hash256, Slot, Uint256,
|
ExecutionPayloadHeaderRefMut, ForkName, ForkVersionedResponse, Hash256, PublicKeyBytes,
|
||||||
|
Signature, SignedBlindedBeaconBlock, SignedRoot, SignedValidatorRegistrationData, Slot,
|
||||||
|
Uint256,
|
||||||
};
|
};
|
||||||
|
use types::{ExecutionBlockHash, SecretKey};
|
||||||
pub type MockBuilderServer = axum::Server<
|
use warp::{Filter, Rejection};
|
||||||
hyper::server::conn::AddrIncoming,
|
|
||||||
axum::routing::IntoMakeService<axum::routing::Router>,
|
|
||||||
>;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Operation {
|
pub enum Operation {
|
||||||
@ -60,115 +39,156 @@ pub enum Operation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Operation {
|
impl Operation {
|
||||||
fn apply<B: BidStuff>(self, bid: &mut B) -> Result<(), MevError> {
|
fn apply<E: EthSpec, B: BidStuff<E>>(self, bid: &mut B) {
|
||||||
match self {
|
match self {
|
||||||
Operation::FeeRecipient(fee_recipient) => {
|
Operation::FeeRecipient(fee_recipient) => bid.set_fee_recipient(fee_recipient),
|
||||||
*bid.fee_recipient_mut() = to_ssz_rs(&fee_recipient)?
|
Operation::GasLimit(gas_limit) => bid.set_gas_limit(gas_limit as u64),
|
||||||
}
|
Operation::Value(value) => bid.set_value(value),
|
||||||
Operation::GasLimit(gas_limit) => *bid.gas_limit_mut() = gas_limit as u64,
|
Operation::ParentHash(parent_hash) => bid.set_parent_hash(parent_hash),
|
||||||
Operation::Value(value) => *bid.value_mut() = to_ssz_rs(&value)?,
|
Operation::PrevRandao(prev_randao) => bid.set_prev_randao(prev_randao),
|
||||||
Operation::ParentHash(parent_hash) => *bid.parent_hash_mut() = to_ssz_rs(&parent_hash)?,
|
Operation::BlockNumber(block_number) => bid.set_block_number(block_number as u64),
|
||||||
Operation::PrevRandao(prev_randao) => *bid.prev_randao_mut() = to_ssz_rs(&prev_randao)?,
|
Operation::Timestamp(timestamp) => bid.set_timestamp(timestamp as u64),
|
||||||
Operation::BlockNumber(block_number) => *bid.block_number_mut() = block_number as u64,
|
Operation::WithdrawalsRoot(root) => bid.set_withdrawals_root(root),
|
||||||
Operation::Timestamp(timestamp) => *bid.timestamp_mut() = timestamp as u64,
|
|
||||||
Operation::WithdrawalsRoot(root) => *bid.withdrawals_root_mut()? = to_ssz_rs(&root)?,
|
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Custom(String);
|
||||||
|
|
||||||
|
impl warp::reject::Reject for Custom {}
|
||||||
|
|
||||||
// contains functions we need for BuilderBids.. not sure what to call this
|
// contains functions we need for BuilderBids.. not sure what to call this
|
||||||
pub trait BidStuff {
|
pub trait BidStuff<E: EthSpec> {
|
||||||
fn fee_recipient_mut(&mut self) -> &mut ExecutionAddress;
|
fn set_fee_recipient(&mut self, fee_recipient_address: Address);
|
||||||
fn gas_limit_mut(&mut self) -> &mut u64;
|
fn set_gas_limit(&mut self, gas_limit: u64);
|
||||||
fn value_mut(&mut self) -> &mut U256;
|
fn set_value(&mut self, value: Uint256);
|
||||||
fn parent_hash_mut(&mut self) -> &mut Hash32;
|
fn set_parent_hash(&mut self, parent_hash: Hash256);
|
||||||
fn prev_randao_mut(&mut self) -> &mut Hash32;
|
fn set_prev_randao(&mut self, randao: Hash256);
|
||||||
fn block_number_mut(&mut self) -> &mut u64;
|
fn set_block_number(&mut self, block_number: u64);
|
||||||
fn timestamp_mut(&mut self) -> &mut u64;
|
fn set_timestamp(&mut self, timestamp: u64);
|
||||||
fn withdrawals_root_mut(&mut self) -> Result<&mut Root, MevError>;
|
fn set_withdrawals_root(&mut self, withdrawals_root: Hash256);
|
||||||
|
|
||||||
fn sign_builder_message(
|
fn sign_builder_message(&mut self, sk: &SecretKey, spec: &ChainSpec) -> Signature;
|
||||||
&mut self,
|
|
||||||
signing_key: &SecretKey,
|
|
||||||
context: &Context,
|
|
||||||
) -> Result<BlsSignature, Error>;
|
|
||||||
|
|
||||||
fn to_signed_bid(self, signature: BlsSignature) -> SignedBuilderBid;
|
fn to_signed_bid(self, signature: Signature) -> SignedBuilderBid<E>;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! map_builder_bid {
|
impl<E: EthSpec> BidStuff<E> for BuilderBid<E> {
|
||||||
($self_ident:ident, |$var:ident| $expr:expr) => {
|
fn set_fee_recipient(&mut self, fee_recipient: Address) {
|
||||||
match $self_ident {
|
match self.to_mut().header_mut() {
|
||||||
BuilderBid::Bellatrix($var) => $expr,
|
ExecutionPayloadHeaderRefMut::Merge(header) => {
|
||||||
BuilderBid::Capella($var) => $expr,
|
header.fee_recipient = fee_recipient;
|
||||||
BuilderBid::Deneb($var) => $expr,
|
}
|
||||||
}
|
ExecutionPayloadHeaderRefMut::Capella(header) => {
|
||||||
};
|
header.fee_recipient = fee_recipient;
|
||||||
}
|
}
|
||||||
|
ExecutionPayloadHeaderRefMut::Deneb(header) => {
|
||||||
impl BidStuff for BuilderBid {
|
header.fee_recipient = fee_recipient;
|
||||||
fn fee_recipient_mut(&mut self) -> &mut ExecutionAddress {
|
}
|
||||||
map_builder_bid!(self, |bid| &mut bid.header.fee_recipient)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gas_limit_mut(&mut self) -> &mut u64 {
|
|
||||||
map_builder_bid!(self, |bid| &mut bid.header.gas_limit)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn value_mut(&mut self) -> &mut U256 {
|
|
||||||
map_builder_bid!(self, |bid| &mut bid.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parent_hash_mut(&mut self) -> &mut Hash32 {
|
|
||||||
map_builder_bid!(self, |bid| &mut bid.header.parent_hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prev_randao_mut(&mut self) -> &mut Hash32 {
|
|
||||||
map_builder_bid!(self, |bid| &mut bid.header.prev_randao)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn block_number_mut(&mut self) -> &mut u64 {
|
|
||||||
map_builder_bid!(self, |bid| &mut bid.header.block_number)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn timestamp_mut(&mut self) -> &mut u64 {
|
|
||||||
map_builder_bid!(self, |bid| &mut bid.header.timestamp)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn withdrawals_root_mut(&mut self) -> Result<&mut Root, MevError> {
|
|
||||||
match self {
|
|
||||||
Self::Bellatrix(_) => Err(MevError::InvalidFork),
|
|
||||||
Self::Capella(bid) => Ok(&mut bid.header.withdrawals_root),
|
|
||||||
Self::Deneb(bid) => Ok(&mut bid.header.withdrawals_root),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign_builder_message(
|
fn set_gas_limit(&mut self, gas_limit: u64) {
|
||||||
&mut self,
|
match self.to_mut().header_mut() {
|
||||||
signing_key: &SecretKey,
|
ExecutionPayloadHeaderRefMut::Merge(header) => {
|
||||||
context: &Context,
|
header.gas_limit = gas_limit;
|
||||||
) -> Result<Signature, Error> {
|
}
|
||||||
map_builder_bid!(self, |message| sign_builder_message(
|
ExecutionPayloadHeaderRefMut::Capella(header) => {
|
||||||
message,
|
header.gas_limit = gas_limit;
|
||||||
signing_key,
|
}
|
||||||
context
|
ExecutionPayloadHeaderRefMut::Deneb(header) => {
|
||||||
))
|
header.gas_limit = gas_limit;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_signed_bid(self, signature: Signature) -> SignedBuilderBid {
|
fn set_value(&mut self, value: Uint256) {
|
||||||
match self {
|
*self.value_mut() = value;
|
||||||
Self::Bellatrix(message) => {
|
}
|
||||||
SignedBuilderBid::Bellatrix(SignedBuilderBidBellatrix { message, signature })
|
|
||||||
|
fn set_parent_hash(&mut self, parent_hash: Hash256) {
|
||||||
|
match self.to_mut().header_mut() {
|
||||||
|
ExecutionPayloadHeaderRefMut::Merge(header) => {
|
||||||
|
header.parent_hash = ExecutionBlockHash::from_root(parent_hash);
|
||||||
}
|
}
|
||||||
Self::Capella(message) => {
|
ExecutionPayloadHeaderRefMut::Capella(header) => {
|
||||||
SignedBuilderBid::Capella(SignedBuilderBidCapella { message, signature })
|
header.parent_hash = ExecutionBlockHash::from_root(parent_hash);
|
||||||
}
|
}
|
||||||
Self::Deneb(message) => {
|
ExecutionPayloadHeaderRefMut::Deneb(header) => {
|
||||||
SignedBuilderBid::Deneb(SignedBuilderBidDeneb { message, signature })
|
header.parent_hash = ExecutionBlockHash::from_root(parent_hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_prev_randao(&mut self, prev_randao: Hash256) {
|
||||||
|
match self.to_mut().header_mut() {
|
||||||
|
ExecutionPayloadHeaderRefMut::Merge(header) => {
|
||||||
|
header.prev_randao = prev_randao;
|
||||||
|
}
|
||||||
|
ExecutionPayloadHeaderRefMut::Capella(header) => {
|
||||||
|
header.prev_randao = prev_randao;
|
||||||
|
}
|
||||||
|
ExecutionPayloadHeaderRefMut::Deneb(header) => {
|
||||||
|
header.prev_randao = prev_randao;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_block_number(&mut self, block_number: u64) {
|
||||||
|
match self.to_mut().header_mut() {
|
||||||
|
ExecutionPayloadHeaderRefMut::Merge(header) => {
|
||||||
|
header.block_number = block_number;
|
||||||
|
}
|
||||||
|
ExecutionPayloadHeaderRefMut::Capella(header) => {
|
||||||
|
header.block_number = block_number;
|
||||||
|
}
|
||||||
|
ExecutionPayloadHeaderRefMut::Deneb(header) => {
|
||||||
|
header.block_number = block_number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_timestamp(&mut self, timestamp: u64) {
|
||||||
|
match self.to_mut().header_mut() {
|
||||||
|
ExecutionPayloadHeaderRefMut::Merge(header) => {
|
||||||
|
header.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
ExecutionPayloadHeaderRefMut::Capella(header) => {
|
||||||
|
header.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
ExecutionPayloadHeaderRefMut::Deneb(header) => {
|
||||||
|
header.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_withdrawals_root(&mut self, withdrawals_root: Hash256) {
|
||||||
|
match self.to_mut().header_mut() {
|
||||||
|
ExecutionPayloadHeaderRefMut::Merge(_) => {
|
||||||
|
panic!("no withdrawals before capella")
|
||||||
|
}
|
||||||
|
ExecutionPayloadHeaderRefMut::Capella(header) => {
|
||||||
|
header.withdrawals_root = withdrawals_root;
|
||||||
|
}
|
||||||
|
ExecutionPayloadHeaderRefMut::Deneb(header) => {
|
||||||
|
header.withdrawals_root = withdrawals_root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sign_builder_message(&mut self, sk: &SecretKey, spec: &ChainSpec) -> Signature {
|
||||||
|
let domain = spec.get_builder_domain();
|
||||||
|
let message = self.signing_root(domain);
|
||||||
|
sk.sign(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_signed_bid(self, signature: Signature) -> SignedBuilderBid<E> {
|
||||||
|
SignedBuilderBid {
|
||||||
|
message: self,
|
||||||
|
signature,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -176,8 +196,7 @@ pub struct MockBuilder<E: EthSpec> {
|
|||||||
el: ExecutionLayer<E>,
|
el: ExecutionLayer<E>,
|
||||||
beacon_client: BeaconNodeHttpClient,
|
beacon_client: BeaconNodeHttpClient,
|
||||||
spec: ChainSpec,
|
spec: ChainSpec,
|
||||||
context: Arc<Context>,
|
val_registration_cache: Arc<RwLock<HashMap<PublicKeyBytes, SignedValidatorRegistrationData>>>,
|
||||||
val_registration_cache: Arc<RwLock<HashMap<BlsPublicKey, SignedValidatorRegistration>>>,
|
|
||||||
builder_sk: SecretKey,
|
builder_sk: SecretKey,
|
||||||
operations: Arc<RwLock<Vec<Operation>>>,
|
operations: Arc<RwLock<Vec<Operation>>>,
|
||||||
invalidate_signatures: Arc<RwLock<bool>>,
|
invalidate_signatures: Arc<RwLock<bool>>,
|
||||||
@ -189,7 +208,7 @@ impl<E: EthSpec> MockBuilder<E> {
|
|||||||
beacon_url: SensitiveUrl,
|
beacon_url: SensitiveUrl,
|
||||||
spec: ChainSpec,
|
spec: ChainSpec,
|
||||||
executor: TaskExecutor,
|
executor: TaskExecutor,
|
||||||
) -> (Self, MockBuilderServer) {
|
) -> (Self, (SocketAddr, impl Future<Output = ()>)) {
|
||||||
let file = NamedTempFile::new().unwrap();
|
let file = NamedTempFile::new().unwrap();
|
||||||
let path = file.path().into();
|
let path = file.path().into();
|
||||||
std::fs::write(&path, hex::encode(DEFAULT_JWT_SECRET)).unwrap();
|
std::fs::write(&path, hex::encode(DEFAULT_JWT_SECRET)).unwrap();
|
||||||
@ -205,23 +224,14 @@ impl<E: EthSpec> MockBuilder<E> {
|
|||||||
let el =
|
let el =
|
||||||
ExecutionLayer::from_config(config, executor.clone(), executor.log().clone()).unwrap();
|
ExecutionLayer::from_config(config, executor.clone(), executor.log().clone()).unwrap();
|
||||||
|
|
||||||
// This should probably be done for all fields, we only update ones we are testing with so far.
|
|
||||||
let mut context = Context::for_mainnet();
|
|
||||||
context.terminal_total_difficulty = to_ssz_rs(&spec.terminal_total_difficulty).unwrap();
|
|
||||||
context.terminal_block_hash = to_ssz_rs(&spec.terminal_block_hash).unwrap();
|
|
||||||
context.terminal_block_hash_activation_epoch =
|
|
||||||
to_ssz_rs(&spec.terminal_block_hash_activation_epoch).unwrap();
|
|
||||||
|
|
||||||
let builder = MockBuilder::new(
|
let builder = MockBuilder::new(
|
||||||
el,
|
el,
|
||||||
BeaconNodeHttpClient::new(beacon_url, Timeouts::set_all(Duration::from_secs(1))),
|
BeaconNodeHttpClient::new(beacon_url, Timeouts::set_all(Duration::from_secs(1))),
|
||||||
spec,
|
spec,
|
||||||
context,
|
|
||||||
);
|
);
|
||||||
let host: Ipv4Addr = Ipv4Addr::LOCALHOST;
|
let host: Ipv4Addr = Ipv4Addr::LOCALHOST;
|
||||||
let port = 0;
|
let port = 0;
|
||||||
let provider = BlindedBlockProviderServer::new(host, port, builder.clone());
|
let server = serve(host, port, builder.clone()).expect("mock builder server should start");
|
||||||
let server = provider.serve();
|
|
||||||
(builder, server)
|
(builder, server)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,15 +239,13 @@ impl<E: EthSpec> MockBuilder<E> {
|
|||||||
el: ExecutionLayer<E>,
|
el: ExecutionLayer<E>,
|
||||||
beacon_client: BeaconNodeHttpClient,
|
beacon_client: BeaconNodeHttpClient,
|
||||||
spec: ChainSpec,
|
spec: ChainSpec,
|
||||||
context: Context,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let sk = SecretKey::random(&mut rand::thread_rng()).unwrap();
|
let sk = SecretKey::random();
|
||||||
Self {
|
Self {
|
||||||
el,
|
el,
|
||||||
beacon_client,
|
beacon_client,
|
||||||
// Should keep spec and context consistent somehow
|
// Should keep spec and context consistent somehow
|
||||||
spec,
|
spec,
|
||||||
context: Arc::new(context),
|
|
||||||
val_registration_cache: Arc::new(RwLock::new(HashMap::new())),
|
val_registration_cache: Arc::new(RwLock::new(HashMap::new())),
|
||||||
builder_sk: sk,
|
builder_sk: sk,
|
||||||
operations: Arc::new(RwLock::new(vec![])),
|
operations: Arc::new(RwLock::new(vec![])),
|
||||||
@ -259,296 +267,335 @@ impl<E: EthSpec> MockBuilder<E> {
|
|||||||
*self.invalidate_signatures.write() = false;
|
*self.invalidate_signatures.write() = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_operations<B: BidStuff>(&self, bid: &mut B) -> Result<(), MevError> {
|
fn apply_operations<B: BidStuff<E>>(&self, bid: &mut B) {
|
||||||
let mut guard = self.operations.write();
|
let mut guard = self.operations.write();
|
||||||
while let Some(op) = guard.pop() {
|
while let Some(op) = guard.pop() {
|
||||||
op.apply(bid)?;
|
op.apply(bid);
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pubkey(&self) -> ethereum_consensus::crypto::PublicKey {
|
|
||||||
self.builder_sk.public_key()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
pub fn serve<E: EthSpec>(
|
||||||
impl<E: EthSpec> mev_rs::BlindedBlockProvider for MockBuilder<E> {
|
listen_addr: Ipv4Addr,
|
||||||
async fn register_validators(
|
listen_port: u16,
|
||||||
&self,
|
builder: MockBuilder<E>,
|
||||||
registrations: &mut [SignedValidatorRegistration],
|
) -> Result<(SocketAddr, impl Future<Output = ()>), crate::test_utils::Error> {
|
||||||
) -> Result<(), MevError> {
|
let inner_ctx = builder.clone();
|
||||||
for registration in registrations {
|
let ctx_filter = warp::any().map(move || inner_ctx.clone());
|
||||||
let pubkey = registration.message.public_key.clone();
|
|
||||||
let message = &mut registration.message;
|
|
||||||
verify_signed_builder_message(
|
|
||||||
message,
|
|
||||||
®istration.signature,
|
|
||||||
&pubkey,
|
|
||||||
&self.context,
|
|
||||||
)?;
|
|
||||||
self.val_registration_cache.write().insert(
|
|
||||||
registration.message.public_key.clone(),
|
|
||||||
registration.clone(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
let prefix = warp::path("eth")
|
||||||
}
|
.and(warp::path("v1"))
|
||||||
|
.and(warp::path("builder"));
|
||||||
|
|
||||||
async fn fetch_best_bid(&self, bid_request: &BidRequest) -> Result<SignedBuilderBid, MevError> {
|
let validators = prefix
|
||||||
let slot = Slot::new(bid_request.slot);
|
.and(warp::path("validators"))
|
||||||
let fork = self.spec.fork_name_at_slot::<E>(slot);
|
.and(warp::body::json())
|
||||||
let signed_cached_data = self
|
.and(warp::path::end())
|
||||||
.val_registration_cache
|
.and(ctx_filter.clone())
|
||||||
.read()
|
.and_then(
|
||||||
.get(&bid_request.public_key)
|
|registrations: Vec<SignedValidatorRegistrationData>, builder: MockBuilder<E>| async move {
|
||||||
.ok_or_else(|| convert_err("missing registration"))?
|
for registration in registrations {
|
||||||
.clone();
|
if !registration.verify_signature(&builder.spec) {
|
||||||
let cached_data = signed_cached_data.message;
|
return Err(reject("invalid signature"));
|
||||||
|
}
|
||||||
|
builder
|
||||||
|
.val_registration_cache
|
||||||
|
.write()
|
||||||
|
.insert(registration.message.pubkey, registration);
|
||||||
|
}
|
||||||
|
Ok(warp::reply())
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
let head = self
|
let blinded_block = prefix
|
||||||
.beacon_client
|
.and(warp::path("blinded_blocks"))
|
||||||
.get_beacon_blocks::<E>(BlockId::Head)
|
.and(warp::body::json())
|
||||||
.await
|
.and(warp::path::end())
|
||||||
.map_err(convert_err)?
|
.and(ctx_filter.clone())
|
||||||
.ok_or_else(|| convert_err("missing head block"))?;
|
.and_then(
|
||||||
|
|block: SignedBlindedBeaconBlock<E>, builder: MockBuilder<E>| async move {
|
||||||
|
let slot = block.slot();
|
||||||
|
let root = match block {
|
||||||
|
SignedBlindedBeaconBlock::Base(_) | types::SignedBeaconBlock::Altair(_) => {
|
||||||
|
return Err(reject("invalid fork"));
|
||||||
|
}
|
||||||
|
SignedBlindedBeaconBlock::Merge(block) => {
|
||||||
|
block.message.body.execution_payload.tree_hash_root()
|
||||||
|
}
|
||||||
|
SignedBlindedBeaconBlock::Capella(block) => {
|
||||||
|
block.message.body.execution_payload.tree_hash_root()
|
||||||
|
}
|
||||||
|
SignedBlindedBeaconBlock::Deneb(block) => {
|
||||||
|
block.message.body.execution_payload.tree_hash_root()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let block = head.data.message();
|
let fork_name = builder.spec.fork_name_at_slot::<E>(slot);
|
||||||
let head_block_root = block.tree_hash_root();
|
let payload = builder
|
||||||
let head_execution_hash = block
|
.el
|
||||||
.body()
|
.get_payload_by_root(&root)
|
||||||
.execution_payload()
|
.ok_or_else(|| reject("missing payload for tx root"))?;
|
||||||
.map_err(convert_err)?
|
let resp = ForkVersionedResponse {
|
||||||
.block_hash();
|
version: Some(fork_name),
|
||||||
if head_execution_hash != from_ssz_rs(&bid_request.parent_hash)? {
|
data: payload,
|
||||||
return Err(custom_err(format!(
|
};
|
||||||
"head mismatch: {} {}",
|
|
||||||
head_execution_hash, bid_request.parent_hash
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
let finalized_execution_hash = self
|
let json_payload = serde_json::to_string(&resp)
|
||||||
.beacon_client
|
.map_err(|_| reject("coudn't serialize response"))?;
|
||||||
.get_beacon_blocks::<E>(BlockId::Finalized)
|
Ok::<_, warp::reject::Rejection>(
|
||||||
.await
|
warp::http::Response::builder()
|
||||||
.map_err(convert_err)?
|
.status(200)
|
||||||
.ok_or_else(|| convert_err("missing finalized block"))?
|
.body(
|
||||||
.data
|
serde_json::to_string(&json_payload)
|
||||||
.message()
|
.map_err(|_| reject("nvalid JSON"))?,
|
||||||
.body()
|
)
|
||||||
.execution_payload()
|
.unwrap(),
|
||||||
.map_err(convert_err)?
|
)
|
||||||
.block_hash();
|
},
|
||||||
|
);
|
||||||
|
|
||||||
let justified_execution_hash = self
|
let status = prefix
|
||||||
.beacon_client
|
.and(warp::path("status"))
|
||||||
.get_beacon_blocks::<E>(BlockId::Justified)
|
.then(|| async { warp::reply() });
|
||||||
.await
|
|
||||||
.map_err(convert_err)?
|
|
||||||
.ok_or_else(|| convert_err("missing finalized block"))?
|
|
||||||
.data
|
|
||||||
.message()
|
|
||||||
.body()
|
|
||||||
.execution_payload()
|
|
||||||
.map_err(convert_err)?
|
|
||||||
.block_hash();
|
|
||||||
|
|
||||||
let val_index = self
|
let header = prefix
|
||||||
.beacon_client
|
.and(warp::path("header"))
|
||||||
.get_beacon_states_validator_id(
|
.and(warp::path::param::<Slot>().or_else(|_| async { Err(reject("Invalid slot")) }))
|
||||||
StateId::Head,
|
.and(
|
||||||
&ValidatorId::PublicKey(from_ssz_rs(&cached_data.public_key)?),
|
warp::path::param::<ExecutionBlockHash>()
|
||||||
)
|
.or_else(|_| async { Err(reject("Invalid parent hash")) }),
|
||||||
.await
|
)
|
||||||
.map_err(convert_err)?
|
.and(
|
||||||
.ok_or_else(|| convert_err("missing validator from state"))?
|
warp::path::param::<PublicKeyBytes>()
|
||||||
.data
|
.or_else(|_| async { Err(reject("Invalid pubkey")) }),
|
||||||
.index;
|
)
|
||||||
let fee_recipient = from_ssz_rs(&cached_data.fee_recipient)?;
|
.and(warp::path::end())
|
||||||
let slots_since_genesis = slot.as_u64() - self.spec.genesis_slot.as_u64();
|
.and(ctx_filter.clone())
|
||||||
|
.and_then(
|
||||||
|
|slot: Slot,
|
||||||
|
parent_hash: ExecutionBlockHash,
|
||||||
|
pubkey: PublicKeyBytes,
|
||||||
|
builder: MockBuilder<E>| async move {
|
||||||
|
let fork = builder.spec.fork_name_at_slot::<E>(slot);
|
||||||
|
let signed_cached_data = builder
|
||||||
|
.val_registration_cache
|
||||||
|
.read()
|
||||||
|
.get(&pubkey)
|
||||||
|
.ok_or_else(|| reject("missing registration"))?
|
||||||
|
.clone();
|
||||||
|
let cached_data = signed_cached_data.message;
|
||||||
|
|
||||||
let genesis_time = self
|
let head = builder
|
||||||
.beacon_client
|
.beacon_client
|
||||||
.get_beacon_genesis()
|
.get_beacon_blocks::<E>(BlockId::Head)
|
||||||
.await
|
|
||||||
.map_err(convert_err)?
|
|
||||||
.data
|
|
||||||
.genesis_time;
|
|
||||||
let timestamp = (slots_since_genesis * self.spec.seconds_per_slot) + genesis_time;
|
|
||||||
|
|
||||||
let head_state: BeaconState<E> = self
|
|
||||||
.beacon_client
|
|
||||||
.get_debug_beacon_states(StateId::Head)
|
|
||||||
.await
|
|
||||||
.map_err(convert_err)?
|
|
||||||
.ok_or_else(|| custom_err("missing head state".to_string()))?
|
|
||||||
.data;
|
|
||||||
let prev_randao = head_state
|
|
||||||
.get_randao_mix(head_state.current_epoch())
|
|
||||||
.map_err(convert_err)?;
|
|
||||||
let expected_withdrawals = match fork {
|
|
||||||
ForkName::Base | ForkName::Altair | ForkName::Merge => None,
|
|
||||||
ForkName::Capella | ForkName::Deneb => Some(
|
|
||||||
self.beacon_client
|
|
||||||
.get_expected_withdrawals(&StateId::Head)
|
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.map_err(|_| reject("couldn't get head"))?
|
||||||
.data,
|
.ok_or_else(|| reject("missing head block"))?;
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
let payload_attributes = match fork {
|
let block = head.data.message();
|
||||||
// the withdrawals root is filled in by operations, but we supply the valid withdrawals
|
let head_block_root = block.tree_hash_root();
|
||||||
// first to avoid polluting the execution block generator with invalid payload attributes
|
let head_execution_hash = block
|
||||||
// NOTE: this was part of an effort to add payload attribute uniqueness checks,
|
.body()
|
||||||
// which was abandoned because it broke too many tests in subtle ways.
|
.execution_payload()
|
||||||
ForkName::Merge | ForkName::Capella => PayloadAttributes::new(
|
.map_err(|_| reject("pre-merge block"))?
|
||||||
timestamp,
|
.block_hash();
|
||||||
*prev_randao,
|
if head_execution_hash != parent_hash {
|
||||||
fee_recipient,
|
return Err(reject("head mismatch"));
|
||||||
expected_withdrawals,
|
}
|
||||||
None,
|
|
||||||
),
|
|
||||||
ForkName::Deneb => PayloadAttributes::new(
|
|
||||||
timestamp,
|
|
||||||
*prev_randao,
|
|
||||||
fee_recipient,
|
|
||||||
expected_withdrawals,
|
|
||||||
Some(head_block_root),
|
|
||||||
),
|
|
||||||
ForkName::Base | ForkName::Altair => {
|
|
||||||
return Err(MevError::InvalidFork);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.el
|
let finalized_execution_hash = builder
|
||||||
.insert_proposer(slot, head_block_root, val_index, payload_attributes.clone())
|
.beacon_client
|
||||||
.await;
|
.get_beacon_blocks::<E>(BlockId::Finalized)
|
||||||
|
.await
|
||||||
|
.map_err(|_| reject("couldn't get finalized block"))?
|
||||||
|
.ok_or_else(|| reject("missing finalized block"))?
|
||||||
|
.data
|
||||||
|
.message()
|
||||||
|
.body()
|
||||||
|
.execution_payload()
|
||||||
|
.map_err(|_| reject("pre-merge block"))?
|
||||||
|
.block_hash();
|
||||||
|
|
||||||
let forkchoice_update_params = ForkchoiceUpdateParameters {
|
let justified_execution_hash = builder
|
||||||
head_root: Hash256::zero(),
|
.beacon_client
|
||||||
head_hash: None,
|
.get_beacon_blocks::<E>(BlockId::Justified)
|
||||||
justified_hash: Some(justified_execution_hash),
|
.await
|
||||||
finalized_hash: Some(finalized_execution_hash),
|
.map_err(|_| reject("couldn't get justified block"))?
|
||||||
};
|
.ok_or_else(|| reject("missing justified block"))?
|
||||||
|
.data
|
||||||
|
.message()
|
||||||
|
.body()
|
||||||
|
.execution_payload()
|
||||||
|
.map_err(|_| reject("pre-merge block"))?
|
||||||
|
.block_hash();
|
||||||
|
|
||||||
let (payload, _block_value, maybe_blobs_bundle): (
|
let val_index = builder
|
||||||
ExecutionPayload<E>,
|
.beacon_client
|
||||||
Uint256,
|
.get_beacon_states_validator_id(StateId::Head, &ValidatorId::PublicKey(pubkey))
|
||||||
Option<BlobsBundle<E>>,
|
.await
|
||||||
) = self
|
.map_err(|_| reject("couldn't get validator"))?
|
||||||
.el
|
.ok_or_else(|| reject("missing validator"))?
|
||||||
.get_full_payload_caching(
|
.data
|
||||||
head_execution_hash,
|
.index;
|
||||||
&payload_attributes,
|
let fee_recipient = cached_data.fee_recipient;
|
||||||
forkchoice_update_params,
|
let slots_since_genesis = slot.as_u64() - builder.spec.genesis_slot.as_u64();
|
||||||
fork,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.map_err(convert_err)?
|
|
||||||
.into();
|
|
||||||
|
|
||||||
let header = match payload {
|
let genesis_data = builder
|
||||||
ExecutionPayload::Merge(payload) => ExecutionPayloadHeader::Merge((&payload).into()),
|
.beacon_client
|
||||||
ExecutionPayload::Capella(payload) => {
|
.get_beacon_genesis()
|
||||||
ExecutionPayloadHeader::Capella((&payload).into())
|
.await
|
||||||
}
|
.map_err(|_| reject("couldn't get beacon genesis"))?
|
||||||
ExecutionPayload::Deneb(payload) => ExecutionPayloadHeader::Deneb((&payload).into()),
|
.data;
|
||||||
};
|
let genesis_time = genesis_data.genesis_time;
|
||||||
|
let timestamp =
|
||||||
|
(slots_since_genesis * builder.spec.seconds_per_slot) + genesis_time;
|
||||||
|
|
||||||
let mut message = match fork {
|
let head_state: BeaconState<E> = builder
|
||||||
ForkName::Deneb => {
|
.beacon_client
|
||||||
let blinded_blobs: BlindedBlobsBundle<E> =
|
.get_debug_beacon_states(StateId::Head)
|
||||||
maybe_blobs_bundle.map(Into::into).unwrap_or_default();
|
.await
|
||||||
BuilderBid::Deneb(BuilderBidDeneb {
|
.map_err(|_| reject("couldn't get state"))?
|
||||||
header: to_ssz_rs(&header)?,
|
.ok_or_else(|| reject("missing state"))?
|
||||||
blinded_blobs_bundle: to_ssz_rs(&blinded_blobs)?,
|
.data;
|
||||||
value: to_ssz_rs(&Uint256::from(DEFAULT_BUILDER_PAYLOAD_VALUE_WEI))?,
|
let prev_randao = head_state
|
||||||
public_key: self.builder_sk.public_key(),
|
.get_randao_mix(head_state.current_epoch())
|
||||||
})
|
.map_err(|_| reject("couldn't get prev randao"))?;
|
||||||
}
|
let expected_withdrawals = match fork {
|
||||||
ForkName::Capella => BuilderBid::Capella(BuilderBidCapella {
|
ForkName::Base | ForkName::Altair | ForkName::Merge => None,
|
||||||
header: to_ssz_rs(&header)?,
|
ForkName::Capella | ForkName::Deneb => Some(
|
||||||
value: to_ssz_rs(&Uint256::from(DEFAULT_BUILDER_PAYLOAD_VALUE_WEI))?,
|
builder
|
||||||
public_key: self.builder_sk.public_key(),
|
.beacon_client
|
||||||
}),
|
.get_expected_withdrawals(&StateId::Head)
|
||||||
ForkName::Merge => BuilderBid::Bellatrix(BuilderBidBellatrix {
|
.await
|
||||||
header: to_ssz_rs(&header)?,
|
.unwrap()
|
||||||
value: to_ssz_rs(&Uint256::from(DEFAULT_BUILDER_PAYLOAD_VALUE_WEI))?,
|
.data,
|
||||||
public_key: self.builder_sk.public_key(),
|
),
|
||||||
}),
|
};
|
||||||
ForkName::Base | ForkName::Altair => return Err(MevError::InvalidFork),
|
|
||||||
};
|
|
||||||
*message.gas_limit_mut() = cached_data.gas_limit;
|
|
||||||
|
|
||||||
self.apply_operations(&mut message)?;
|
let payload_attributes = match fork {
|
||||||
let mut signature =
|
// the withdrawals root is filled in by operations, but we supply the valid withdrawals
|
||||||
message.sign_builder_message(&self.builder_sk, self.context.as_ref())?;
|
// first to avoid polluting the execution block generator with invalid payload attributes
|
||||||
|
// NOTE: this was part of an effort to add payload attribute uniqueness checks,
|
||||||
|
// which was abandoned because it broke too many tests in subtle ways.
|
||||||
|
ForkName::Merge | ForkName::Capella => PayloadAttributes::new(
|
||||||
|
timestamp,
|
||||||
|
*prev_randao,
|
||||||
|
fee_recipient,
|
||||||
|
expected_withdrawals,
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
ForkName::Deneb => PayloadAttributes::new(
|
||||||
|
timestamp,
|
||||||
|
*prev_randao,
|
||||||
|
fee_recipient,
|
||||||
|
expected_withdrawals,
|
||||||
|
Some(head_block_root),
|
||||||
|
),
|
||||||
|
ForkName::Base | ForkName::Altair => {
|
||||||
|
return Err(reject("invalid fork"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if *self.invalidate_signatures.read() {
|
builder
|
||||||
signature = Signature::default();
|
.el
|
||||||
}
|
.insert_proposer(slot, head_block_root, val_index, payload_attributes.clone())
|
||||||
|
.await;
|
||||||
|
|
||||||
Ok(message.to_signed_bid(signature))
|
let forkchoice_update_params = ForkchoiceUpdateParameters {
|
||||||
}
|
head_root: Hash256::zero(),
|
||||||
|
head_hash: None,
|
||||||
|
justified_hash: Some(justified_execution_hash),
|
||||||
|
finalized_hash: Some(finalized_execution_hash),
|
||||||
|
};
|
||||||
|
|
||||||
async fn open_bid(
|
let (payload, _block_value, maybe_blobs_bundle): (
|
||||||
&self,
|
ExecutionPayload<E>,
|
||||||
signed_block: &mut SignedBlindedBeaconBlock,
|
Uint256,
|
||||||
) -> Result<ServerPayload, MevError> {
|
Option<BlobsBundle<E>>,
|
||||||
let node = match signed_block {
|
) = builder
|
||||||
SignedBlindedBeaconBlock::Bellatrix(block) => {
|
.el
|
||||||
block.message.body.execution_payload_header.hash_tree_root()
|
.get_full_payload_caching(
|
||||||
}
|
head_execution_hash,
|
||||||
SignedBlindedBeaconBlock::Capella(block) => {
|
&payload_attributes,
|
||||||
block.message.body.execution_payload_header.hash_tree_root()
|
forkchoice_update_params,
|
||||||
}
|
fork,
|
||||||
SignedBlindedBeaconBlock::Deneb(block_and_blobs) => block_and_blobs
|
)
|
||||||
.signed_blinded_block
|
.await
|
||||||
.message
|
.map_err(|_| reject("couldn't get payload"))?
|
||||||
.body
|
.into();
|
||||||
.execution_payload_header
|
|
||||||
.hash_tree_root(),
|
|
||||||
}
|
|
||||||
.map_err(convert_err)?;
|
|
||||||
|
|
||||||
let payload = self
|
let mut message = match fork {
|
||||||
.el
|
ForkName::Deneb => BuilderBid::Deneb(BuilderBidDeneb {
|
||||||
.get_payload_by_root(&from_ssz_rs(&node)?)
|
header: payload
|
||||||
.ok_or_else(|| convert_err("missing payload for tx root"))?;
|
.as_deneb()
|
||||||
|
.map_err(|_| reject("incorrect payload variant"))?
|
||||||
|
.into(),
|
||||||
|
blinded_blobs_bundle: maybe_blobs_bundle
|
||||||
|
.map(Into::into)
|
||||||
|
.unwrap_or_default(),
|
||||||
|
value: Uint256::from(DEFAULT_BUILDER_PAYLOAD_VALUE_WEI),
|
||||||
|
pubkey: builder.builder_sk.public_key().compress(),
|
||||||
|
}),
|
||||||
|
ForkName::Capella => BuilderBid::Capella(BuilderBidCapella {
|
||||||
|
header: payload
|
||||||
|
.as_capella()
|
||||||
|
.map_err(|_| reject("incorrect payload variant"))?
|
||||||
|
.into(),
|
||||||
|
value: Uint256::from(DEFAULT_BUILDER_PAYLOAD_VALUE_WEI),
|
||||||
|
pubkey: builder.builder_sk.public_key().compress(),
|
||||||
|
}),
|
||||||
|
ForkName::Merge => BuilderBid::Merge(BuilderBidMerge {
|
||||||
|
header: payload
|
||||||
|
.as_merge()
|
||||||
|
.map_err(|_| reject("incorrect payload variant"))?
|
||||||
|
.into(),
|
||||||
|
value: Uint256::from(DEFAULT_BUILDER_PAYLOAD_VALUE_WEI),
|
||||||
|
pubkey: builder.builder_sk.public_key().compress(),
|
||||||
|
}),
|
||||||
|
ForkName::Base | ForkName::Altair => return Err(reject("invalid fork")),
|
||||||
|
};
|
||||||
|
|
||||||
let fork = payload.payload_ref().fork_name();
|
message.set_gas_limit(cached_data.gas_limit);
|
||||||
let resp = ForkVersionedResponse {
|
|
||||||
version: Some(fork),
|
|
||||||
data: payload,
|
|
||||||
};
|
|
||||||
|
|
||||||
let json_payload = serde_json::to_string(&resp).map_err(convert_err)?;
|
builder.apply_operations(&mut message);
|
||||||
serde_json::from_str(json_payload.as_str()).map_err(convert_err)
|
|
||||||
}
|
let mut signature =
|
||||||
|
message.sign_builder_message(&builder.builder_sk, &builder.spec);
|
||||||
|
|
||||||
|
if *builder.invalidate_signatures.read() {
|
||||||
|
signature = Signature::empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
let fork_name = builder
|
||||||
|
.spec
|
||||||
|
.fork_name_at_epoch(slot.epoch(E::slots_per_epoch()));
|
||||||
|
let signed_bid = SignedBuilderBid { message, signature };
|
||||||
|
let resp = ForkVersionedResponse {
|
||||||
|
version: Some(fork_name),
|
||||||
|
data: signed_bid,
|
||||||
|
};
|
||||||
|
let json_bid = serde_json::to_string(&resp)
|
||||||
|
.map_err(|_| reject("coudn't serialize signed bid"))?;
|
||||||
|
Ok::<_, Rejection>(
|
||||||
|
warp::http::Response::builder()
|
||||||
|
.status(200)
|
||||||
|
.body(json_bid)
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let routes = warp::post()
|
||||||
|
.and(validators.or(blinded_block))
|
||||||
|
.or(warp::get().and(status).or(header))
|
||||||
|
.map(|reply| warp::reply::with_header(reply, "Server", "lighthouse-mock-builder-server"));
|
||||||
|
|
||||||
|
let (listening_socket, server) = warp::serve(routes)
|
||||||
|
.try_bind_ephemeral(SocketAddrV4::new(listen_addr, listen_port))
|
||||||
|
.expect("mock builder server should start");
|
||||||
|
Ok((listening_socket, server))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_ssz_rs<T: SimpleSerialize, U: Decode>(ssz_rs_data: &T) -> Result<U, MevError> {
|
fn reject(msg: &'static str) -> Rejection {
|
||||||
U::from_ssz_bytes(
|
warp::reject::custom(Custom(msg.to_string()))
|
||||||
ssz_rs::serialize(ssz_rs_data)
|
|
||||||
.map_err(convert_err)?
|
|
||||||
.as_ref(),
|
|
||||||
)
|
|
||||||
.map_err(convert_err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_ssz_rs<T: Encode, U: SimpleSerialize>(ssz_data: &T) -> Result<U, MevError> {
|
|
||||||
ssz_rs::deserialize::<U>(&ssz_data.as_ssz_bytes()).map_err(convert_err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn convert_err<E: Debug>(e: E) -> MevError {
|
|
||||||
custom_err(format!("{e:?}"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a bit of a hack since the `Custom` variant was removed from `mev_rs::Error`.
|
|
||||||
pub fn custom_err(s: String) -> MevError {
|
|
||||||
MevError::Consensus(ethereum_consensus::state_transition::Error::Io(
|
|
||||||
std::io::Error::new(std::io::ErrorKind::Other, s),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,7 @@ pub use execution_block_generator::{
|
|||||||
Block, ExecutionBlockGenerator,
|
Block, ExecutionBlockGenerator,
|
||||||
};
|
};
|
||||||
pub use hook::Hook;
|
pub use hook::Hook;
|
||||||
pub use mock_builder::{
|
pub use mock_builder::{MockBuilder, Operation};
|
||||||
convert_err, custom_err, from_ssz_rs, to_ssz_rs, Context as MockBuilderContext, MockBuilder,
|
|
||||||
MockBuilderServer, Operation,
|
|
||||||
};
|
|
||||||
pub use mock_execution_layer::MockExecutionLayer;
|
pub use mock_execution_layer::MockExecutionLayer;
|
||||||
|
|
||||||
pub const DEFAULT_TERMINAL_DIFFICULTY: u64 = 6400;
|
pub const DEFAULT_TERMINAL_DIFFICULTY: u64 = 6400;
|
||||||
|
@ -1632,13 +1632,19 @@ pub fn serve<T: BeaconChainTypes>(
|
|||||||
|block_id: BlockId,
|
|block_id: BlockId,
|
||||||
task_spawner: TaskSpawner<T::EthSpec>,
|
task_spawner: TaskSpawner<T::EthSpec>,
|
||||||
chain: Arc<BeaconChain<T>>| {
|
chain: Arc<BeaconChain<T>>| {
|
||||||
task_spawner.blocking_json_task(Priority::P1, move || {
|
// Prioritise requests for the head block root, as it is used by some VCs (including
|
||||||
let (block, execution_optimistic, finalized) =
|
// the Lighthouse VC) to create sync committee messages.
|
||||||
block_id.blinded_block(&chain)?;
|
let priority = if let BlockId(eth2::types::BlockId::Head) = block_id {
|
||||||
Ok(api_types::GenericResponse::from(api_types::RootData::from(
|
Priority::P0
|
||||||
block.canonical_root(),
|
} else {
|
||||||
))
|
Priority::P1
|
||||||
.add_execution_optimistic_finalized(execution_optimistic, finalized))
|
};
|
||||||
|
task_spawner.blocking_json_task(priority, move || {
|
||||||
|
let (block_root, execution_optimistic, finalized) = block_id.root(&chain)?;
|
||||||
|
Ok(
|
||||||
|
api_types::GenericResponse::from(api_types::RootData::from(block_root))
|
||||||
|
.add_execution_optimistic_finalized(execution_optimistic, finalized),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -267,11 +267,7 @@ impl ApiTester {
|
|||||||
|
|
||||||
// Start the mock builder service prior to building the chain out.
|
// Start the mock builder service prior to building the chain out.
|
||||||
harness.runtime.task_executor.spawn(
|
harness.runtime.task_executor.spawn(
|
||||||
async move {
|
async move { mock_builder_server.await },
|
||||||
if let Err(e) = mock_builder_server.await {
|
|
||||||
panic!("error in mock builder server: {e:?}");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mock_builder_server",
|
"mock_builder_server",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -11,11 +11,17 @@ use libp2p::Multiaddr;
|
|||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||||
|
use std::num::NonZeroU16;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use types::{ForkContext, ForkName};
|
use types::{ForkContext, ForkName};
|
||||||
|
|
||||||
|
pub const DEFAULT_IPV4_ADDRESS: Ipv4Addr = Ipv4Addr::UNSPECIFIED;
|
||||||
|
pub const DEFAULT_TCP_PORT: u16 = 9000u16;
|
||||||
|
pub const DEFAULT_DISC_PORT: u16 = 9000u16;
|
||||||
|
pub const DEFAULT_QUIC_PORT: u16 = 9001u16;
|
||||||
|
|
||||||
/// The cache time is set to accommodate the circulation time of an attestation.
|
/// The cache time is set to accommodate the circulation time of an attestation.
|
||||||
///
|
///
|
||||||
/// The p2p spec declares that we accept attestations within the following range:
|
/// The p2p spec declares that we accept attestations within the following range:
|
||||||
@ -59,22 +65,22 @@ pub struct Config {
|
|||||||
pub enr_address: (Option<Ipv4Addr>, Option<Ipv6Addr>),
|
pub enr_address: (Option<Ipv4Addr>, Option<Ipv6Addr>),
|
||||||
|
|
||||||
/// The udp ipv4 port to broadcast to peers in order to reach back for discovery.
|
/// The udp ipv4 port to broadcast to peers in order to reach back for discovery.
|
||||||
pub enr_udp4_port: Option<u16>,
|
pub enr_udp4_port: Option<NonZeroU16>,
|
||||||
|
|
||||||
/// The quic ipv4 port to broadcast to peers in order to reach back for libp2p services.
|
/// The quic ipv4 port to broadcast to peers in order to reach back for libp2p services.
|
||||||
pub enr_quic4_port: Option<u16>,
|
pub enr_quic4_port: Option<NonZeroU16>,
|
||||||
|
|
||||||
/// The tcp ipv4 port to broadcast to peers in order to reach back for libp2p services.
|
/// The tcp ipv4 port to broadcast to peers in order to reach back for libp2p services.
|
||||||
pub enr_tcp4_port: Option<u16>,
|
pub enr_tcp4_port: Option<NonZeroU16>,
|
||||||
|
|
||||||
/// The udp ipv6 port to broadcast to peers in order to reach back for discovery.
|
/// The udp ipv6 port to broadcast to peers in order to reach back for discovery.
|
||||||
pub enr_udp6_port: Option<u16>,
|
pub enr_udp6_port: Option<NonZeroU16>,
|
||||||
|
|
||||||
/// The tcp ipv6 port to broadcast to peers in order to reach back for libp2p services.
|
/// The tcp ipv6 port to broadcast to peers in order to reach back for libp2p services.
|
||||||
pub enr_tcp6_port: Option<u16>,
|
pub enr_tcp6_port: Option<NonZeroU16>,
|
||||||
|
|
||||||
/// The quic ipv6 port to broadcast to peers in order to reach back for libp2p services.
|
/// The quic ipv6 port to broadcast to peers in order to reach back for libp2p services.
|
||||||
pub enr_quic6_port: Option<u16>,
|
pub enr_quic6_port: Option<NonZeroU16>,
|
||||||
|
|
||||||
/// Target number of connected peers.
|
/// Target number of connected peers.
|
||||||
pub target_peers: usize,
|
pub target_peers: usize,
|
||||||
@ -304,10 +310,10 @@ impl Default for Config {
|
|||||||
.expect("The total rate limit has been specified"),
|
.expect("The total rate limit has been specified"),
|
||||||
);
|
);
|
||||||
let listen_addresses = ListenAddress::V4(ListenAddr {
|
let listen_addresses = ListenAddress::V4(ListenAddr {
|
||||||
addr: Ipv4Addr::UNSPECIFIED,
|
addr: DEFAULT_IPV4_ADDRESS,
|
||||||
disc_port: 9000,
|
disc_port: DEFAULT_DISC_PORT,
|
||||||
quic_port: 9001,
|
quic_port: DEFAULT_QUIC_PORT,
|
||||||
tcp_port: 9000,
|
tcp_port: DEFAULT_TCP_PORT,
|
||||||
});
|
});
|
||||||
|
|
||||||
let discv5_listen_config =
|
let discv5_listen_config =
|
||||||
|
@ -158,11 +158,11 @@ pub fn create_enr_builder_from_config<T: EnrKey>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(udp4_port) = config.enr_udp4_port {
|
if let Some(udp4_port) = config.enr_udp4_port {
|
||||||
builder.udp4(udp4_port);
|
builder.udp4(udp4_port.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(udp6_port) = config.enr_udp6_port {
|
if let Some(udp6_port) = config.enr_udp6_port {
|
||||||
builder.udp6(udp6_port);
|
builder.udp6(udp6_port.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if enable_libp2p {
|
if enable_libp2p {
|
||||||
@ -171,35 +171,45 @@ pub fn create_enr_builder_from_config<T: EnrKey>(
|
|||||||
// the related fields should only be added when both QUIC and libp2p are enabled
|
// the related fields should only be added when both QUIC and libp2p are enabled
|
||||||
if !config.disable_quic_support {
|
if !config.disable_quic_support {
|
||||||
// If we are listening on ipv4, add the quic ipv4 port.
|
// If we are listening on ipv4, add the quic ipv4 port.
|
||||||
if let Some(quic4_port) = config
|
if let Some(quic4_port) = config.enr_quic4_port.or_else(|| {
|
||||||
.enr_quic4_port
|
config
|
||||||
.or_else(|| config.listen_addrs().v4().map(|v4_addr| v4_addr.quic_port))
|
.listen_addrs()
|
||||||
{
|
.v4()
|
||||||
builder.add_value(QUIC_ENR_KEY, &quic4_port);
|
.and_then(|v4_addr| v4_addr.quic_port.try_into().ok())
|
||||||
|
}) {
|
||||||
|
builder.add_value(QUIC_ENR_KEY, &quic4_port.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are listening on ipv6, add the quic ipv6 port.
|
// If we are listening on ipv6, add the quic ipv6 port.
|
||||||
if let Some(quic6_port) = config
|
if let Some(quic6_port) = config.enr_quic6_port.or_else(|| {
|
||||||
.enr_quic6_port
|
config
|
||||||
.or_else(|| config.listen_addrs().v6().map(|v6_addr| v6_addr.quic_port))
|
.listen_addrs()
|
||||||
{
|
.v6()
|
||||||
builder.add_value(QUIC6_ENR_KEY, &quic6_port);
|
.and_then(|v6_addr| v6_addr.quic_port.try_into().ok())
|
||||||
|
}) {
|
||||||
|
builder.add_value(QUIC6_ENR_KEY, &quic6_port.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the ENR port is not set, and we are listening over that ip version, use the listening port instead.
|
// If the ENR port is not set, and we are listening over that ip version, use the listening port instead.
|
||||||
let tcp4_port = config
|
let tcp4_port = config.enr_tcp4_port.or_else(|| {
|
||||||
.enr_tcp4_port
|
config
|
||||||
.or_else(|| config.listen_addrs().v4().map(|v4_addr| v4_addr.tcp_port));
|
.listen_addrs()
|
||||||
|
.v4()
|
||||||
|
.and_then(|v4_addr| v4_addr.tcp_port.try_into().ok())
|
||||||
|
});
|
||||||
if let Some(tcp4_port) = tcp4_port {
|
if let Some(tcp4_port) = tcp4_port {
|
||||||
builder.tcp4(tcp4_port);
|
builder.tcp4(tcp4_port.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
let tcp6_port = config
|
let tcp6_port = config.enr_tcp6_port.or_else(|| {
|
||||||
.enr_tcp6_port
|
config
|
||||||
.or_else(|| config.listen_addrs().v6().map(|v6_addr| v6_addr.tcp_port));
|
.listen_addrs()
|
||||||
|
.v6()
|
||||||
|
.and_then(|v6_addr| v6_addr.tcp_port.try_into().ok())
|
||||||
|
});
|
||||||
if let Some(tcp6_port) = tcp6_port {
|
if let Some(tcp6_port) = tcp6_port {
|
||||||
builder.tcp6(tcp6_port);
|
builder.tcp6(tcp6_port.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builder
|
builder
|
||||||
|
@ -21,10 +21,11 @@ pub use libp2p::identity::{Keypair, PublicKey};
|
|||||||
use enr::{ATTESTATION_BITFIELD_ENR_KEY, ETH2_ENR_KEY, SYNC_COMMITTEE_BITFIELD_ENR_KEY};
|
use enr::{ATTESTATION_BITFIELD_ENR_KEY, ETH2_ENR_KEY, SYNC_COMMITTEE_BITFIELD_ENR_KEY};
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use futures::stream::FuturesUnordered;
|
use futures::stream::FuturesUnordered;
|
||||||
|
use libp2p::multiaddr::Protocol;
|
||||||
use libp2p::swarm::behaviour::{DialFailure, FromSwarm};
|
use libp2p::swarm::behaviour::{DialFailure, FromSwarm};
|
||||||
use libp2p::swarm::THandlerInEvent;
|
use libp2p::swarm::THandlerInEvent;
|
||||||
pub use libp2p::{
|
pub use libp2p::{
|
||||||
core::{ConnectedPoint, Multiaddr},
|
core::{transport::ListenerId, ConnectedPoint, Multiaddr},
|
||||||
identity::PeerId,
|
identity::PeerId,
|
||||||
swarm::{
|
swarm::{
|
||||||
dummy::ConnectionHandler, ConnectionId, DialError, NetworkBehaviour, NotifyHandler,
|
dummy::ConnectionHandler, ConnectionId, DialError, NetworkBehaviour, NotifyHandler,
|
||||||
@ -77,6 +78,19 @@ pub struct DiscoveredPeers {
|
|||||||
pub peers: HashMap<Enr, Option<Instant>>,
|
pub peers: HashMap<Enr, Option<Instant>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Specifies which port numbers should be modified after start of the discovery service
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct UpdatePorts {
|
||||||
|
/// TCP port associated wih IPv4 address (if present)
|
||||||
|
pub tcp4: bool,
|
||||||
|
/// TCP port associated wih IPv6 address (if present)
|
||||||
|
pub tcp6: bool,
|
||||||
|
/// QUIC port associated wih IPv4 address (if present)
|
||||||
|
pub quic4: bool,
|
||||||
|
/// QUIC port associated wih IPv6 address (if present)
|
||||||
|
pub quic6: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
struct SubnetQuery {
|
struct SubnetQuery {
|
||||||
subnet: Subnet,
|
subnet: Subnet,
|
||||||
@ -177,12 +191,8 @@ pub struct Discovery<TSpec: EthSpec> {
|
|||||||
/// always false.
|
/// always false.
|
||||||
pub started: bool,
|
pub started: bool,
|
||||||
|
|
||||||
/// This keeps track of whether an external UDP port change should also indicate an internal
|
/// Specifies whether various port numbers should be updated after the discovery service has been started
|
||||||
/// TCP port change. As we cannot detect our external TCP port, we assume that the external UDP
|
update_ports: UpdatePorts,
|
||||||
/// port is also our external TCP port. This assumption only holds if the user has not
|
|
||||||
/// explicitly set their ENR TCP port via the CLI config. The first indicates tcp4 and the
|
|
||||||
/// second indicates tcp6.
|
|
||||||
update_tcp_port: (bool, bool),
|
|
||||||
|
|
||||||
/// Logger for the discovery behaviour.
|
/// Logger for the discovery behaviour.
|
||||||
log: slog::Logger,
|
log: slog::Logger,
|
||||||
@ -300,10 +310,12 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let update_tcp_port = (
|
let update_ports = UpdatePorts {
|
||||||
config.enr_tcp4_port.is_none(),
|
tcp4: config.enr_tcp4_port.is_none(),
|
||||||
config.enr_tcp6_port.is_none(),
|
tcp6: config.enr_tcp6_port.is_none(),
|
||||||
);
|
quic4: config.enr_quic4_port.is_none(),
|
||||||
|
quic6: config.enr_quic6_port.is_none(),
|
||||||
|
};
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
cached_enrs: LruCache::new(50),
|
cached_enrs: LruCache::new(50),
|
||||||
@ -314,7 +326,7 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
|
|||||||
discv5,
|
discv5,
|
||||||
event_stream,
|
event_stream,
|
||||||
started: !config.disable_discovery,
|
started: !config.disable_discovery,
|
||||||
update_tcp_port,
|
update_ports,
|
||||||
log,
|
log,
|
||||||
enr_dir,
|
enr_dir,
|
||||||
})
|
})
|
||||||
@ -555,8 +567,6 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
|
|||||||
if let Ok(node_id) = peer_id_to_node_id(peer_id) {
|
if let Ok(node_id) = peer_id_to_node_id(peer_id) {
|
||||||
// If we could convert this peer id, remove it from the DHT and ban it from discovery.
|
// If we could convert this peer id, remove it from the DHT and ban it from discovery.
|
||||||
self.discv5.ban_node(&node_id, None);
|
self.discv5.ban_node(&node_id, None);
|
||||||
// Remove the node from the routing table.
|
|
||||||
self.discv5.remove_node(&node_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for ip_address in ip_addresses {
|
for ip_address in ip_addresses {
|
||||||
@ -1006,8 +1016,8 @@ impl<TSpec: EthSpec> NetworkBehaviour for Discovery<TSpec> {
|
|||||||
// Discv5 will have updated our local ENR. We save the updated version
|
// Discv5 will have updated our local ENR. We save the updated version
|
||||||
// to disk.
|
// to disk.
|
||||||
|
|
||||||
if (self.update_tcp_port.0 && socket_addr.is_ipv4())
|
if (self.update_ports.tcp4 && socket_addr.is_ipv4())
|
||||||
|| (self.update_tcp_port.1 && socket_addr.is_ipv6())
|
|| (self.update_ports.tcp6 && socket_addr.is_ipv6())
|
||||||
{
|
{
|
||||||
// Update the TCP port in the ENR
|
// Update the TCP port in the ENR
|
||||||
self.discv5.update_local_enr_socket(socket_addr, true);
|
self.discv5.update_local_enr_socket(socket_addr, true);
|
||||||
@ -1036,12 +1046,79 @@ impl<TSpec: EthSpec> NetworkBehaviour for Discovery<TSpec> {
|
|||||||
FromSwarm::DialFailure(DialFailure { peer_id, error, .. }) => {
|
FromSwarm::DialFailure(DialFailure { peer_id, error, .. }) => {
|
||||||
self.on_dial_failure(peer_id, error)
|
self.on_dial_failure(peer_id, error)
|
||||||
}
|
}
|
||||||
|
FromSwarm::NewListenAddr(ev) => {
|
||||||
|
let addr = ev.addr;
|
||||||
|
let listener_id = ev.listener_id;
|
||||||
|
|
||||||
|
trace!(self.log, "Received NewListenAddr event from swarm"; "listener_id" => ?listener_id, "addr" => ?addr);
|
||||||
|
|
||||||
|
let mut addr_iter = addr.iter();
|
||||||
|
|
||||||
|
let attempt_enr_update = match addr_iter.next() {
|
||||||
|
Some(Protocol::Ip4(_)) => match (addr_iter.next(), addr_iter.next()) {
|
||||||
|
(Some(Protocol::Tcp(port)), None) => {
|
||||||
|
if !self.update_ports.tcp4 {
|
||||||
|
debug!(self.log, "Skipping ENR update"; "multiaddr" => ?addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.update_enr_tcp_port(port)
|
||||||
|
}
|
||||||
|
(Some(Protocol::Udp(port)), Some(Protocol::QuicV1)) => {
|
||||||
|
if !self.update_ports.quic4 {
|
||||||
|
debug!(self.log, "Skipping ENR update"; "multiaddr" => ?addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.update_enr_quic_port(port)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
debug!(self.log, "Encountered unacceptable multiaddr for listening (unsupported transport)"; "addr" => ?addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Some(Protocol::Ip6(_)) => match (addr_iter.next(), addr_iter.next()) {
|
||||||
|
(Some(Protocol::Tcp(port)), None) => {
|
||||||
|
if !self.update_ports.tcp6 {
|
||||||
|
debug!(self.log, "Skipping ENR update"; "multiaddr" => ?addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.update_enr_tcp_port(port)
|
||||||
|
}
|
||||||
|
(Some(Protocol::Udp(port)), Some(Protocol::QuicV1)) => {
|
||||||
|
if !self.update_ports.quic6 {
|
||||||
|
debug!(self.log, "Skipping ENR update"; "multiaddr" => ?addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.update_enr_quic_port(port)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
debug!(self.log, "Encountered unacceptable multiaddr for listening (unsupported transport)"; "addr" => ?addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
debug!(self.log, "Encountered unacceptable multiaddr for listening (no IP)"; "addr" => ?addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let local_enr: Enr = self.discv5.local_enr();
|
||||||
|
|
||||||
|
match attempt_enr_update {
|
||||||
|
Ok(_) => {
|
||||||
|
info!(self.log, "Updated local ENR"; "enr" => local_enr.to_base64(), "seq" => local_enr.seq(), "id"=> %local_enr.node_id(), "ip4" => ?local_enr.ip4(), "udp4"=> ?local_enr.udp4(), "tcp4" => ?local_enr.tcp4(), "tcp6" => ?local_enr.tcp6(), "udp6" => ?local_enr.udp6())
|
||||||
|
}
|
||||||
|
Err(e) => warn!(self.log, "Failed to update ENR"; "error" => ?e),
|
||||||
|
}
|
||||||
|
}
|
||||||
FromSwarm::ConnectionEstablished(_)
|
FromSwarm::ConnectionEstablished(_)
|
||||||
| FromSwarm::ConnectionClosed(_)
|
| FromSwarm::ConnectionClosed(_)
|
||||||
| FromSwarm::AddressChange(_)
|
| FromSwarm::AddressChange(_)
|
||||||
| FromSwarm::ListenFailure(_)
|
| FromSwarm::ListenFailure(_)
|
||||||
| FromSwarm::NewListener(_)
|
| FromSwarm::NewListener(_)
|
||||||
| FromSwarm::NewListenAddr(_)
|
|
||||||
| FromSwarm::ExpiredListenAddr(_)
|
| FromSwarm::ExpiredListenAddr(_)
|
||||||
| FromSwarm::ListenerError(_)
|
| FromSwarm::ListenerError(_)
|
||||||
| FromSwarm::ListenerClosed(_)
|
| FromSwarm::ListenerClosed(_)
|
||||||
|
@ -415,7 +415,7 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
|
|||||||
/// Reports if a peer is banned or not.
|
/// Reports if a peer is banned or not.
|
||||||
///
|
///
|
||||||
/// This is used to determine if we should accept incoming connections.
|
/// This is used to determine if we should accept incoming connections.
|
||||||
pub fn ban_status(&self, peer_id: &PeerId) -> BanResult {
|
pub fn ban_status(&self, peer_id: &PeerId) -> Option<BanResult> {
|
||||||
self.network_globals.peers.read().ban_status(peer_id)
|
self.network_globals.peers.read().ban_status(peer_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -815,7 +815,7 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
|
|||||||
) -> bool {
|
) -> bool {
|
||||||
{
|
{
|
||||||
let mut peerdb = self.network_globals.peers.write();
|
let mut peerdb = self.network_globals.peers.write();
|
||||||
if !matches!(peerdb.ban_status(peer_id), BanResult::NotBanned) {
|
if peerdb.ban_status(peer_id).is_some() {
|
||||||
// don't connect if the peer is banned
|
// don't connect if the peer is banned
|
||||||
error!(self.log, "Connection has been allowed to a banned peer"; "peer_id" => %peer_id);
|
error!(self.log, "Connection has been allowed to a banned peer"; "peer_id" => %peer_id);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
//! Implementation of [`NetworkBehaviour`] for the [`PeerManager`].
|
//! Implementation of [`NetworkBehaviour`] for the [`PeerManager`].
|
||||||
|
|
||||||
|
use std::net::IpAddr;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
@ -8,17 +9,17 @@ use libp2p::identity::PeerId;
|
|||||||
use libp2p::swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm};
|
use libp2p::swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm};
|
||||||
use libp2p::swarm::dial_opts::{DialOpts, PeerCondition};
|
use libp2p::swarm::dial_opts::{DialOpts, PeerCondition};
|
||||||
use libp2p::swarm::dummy::ConnectionHandler;
|
use libp2p::swarm::dummy::ConnectionHandler;
|
||||||
use libp2p::swarm::{ConnectionId, NetworkBehaviour, PollParameters, ToSwarm};
|
use libp2p::swarm::{ConnectionDenied, ConnectionId, NetworkBehaviour, PollParameters, ToSwarm};
|
||||||
use slog::{debug, error};
|
use slog::{debug, error, trace};
|
||||||
use types::EthSpec;
|
use types::EthSpec;
|
||||||
|
|
||||||
use crate::discovery::enr_ext::EnrExt;
|
use crate::discovery::enr_ext::EnrExt;
|
||||||
|
use crate::peer_manager::peerdb::BanResult;
|
||||||
use crate::rpc::GoodbyeReason;
|
use crate::rpc::GoodbyeReason;
|
||||||
use crate::types::SyncState;
|
use crate::types::SyncState;
|
||||||
use crate::{metrics, ClearDialError};
|
use crate::{metrics, ClearDialError};
|
||||||
|
|
||||||
use super::peerdb::BanResult;
|
use super::{ConnectingType, PeerManager, PeerManagerEvent};
|
||||||
use super::{ConnectingType, PeerManager, PeerManagerEvent, ReportSource};
|
|
||||||
|
|
||||||
impl<TSpec: EthSpec> NetworkBehaviour for PeerManager<TSpec> {
|
impl<TSpec: EthSpec> NetworkBehaviour for PeerManager<TSpec> {
|
||||||
type ConnectionHandler = ConnectionHandler;
|
type ConnectionHandler = ConnectionHandler;
|
||||||
@ -169,26 +170,64 @@ impl<TSpec: EthSpec> NetworkBehaviour for PeerManager<TSpec> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_pending_inbound_connection(
|
||||||
|
&mut self,
|
||||||
|
_connection_id: ConnectionId,
|
||||||
|
_local_addr: &libp2p::Multiaddr,
|
||||||
|
remote_addr: &libp2p::Multiaddr,
|
||||||
|
) -> Result<(), ConnectionDenied> {
|
||||||
|
// get the IP address to verify it's not banned.
|
||||||
|
let ip = match remote_addr.iter().next() {
|
||||||
|
Some(libp2p::multiaddr::Protocol::Ip6(ip)) => IpAddr::V6(ip),
|
||||||
|
Some(libp2p::multiaddr::Protocol::Ip4(ip)) => IpAddr::V4(ip),
|
||||||
|
_ => {
|
||||||
|
return Err(ConnectionDenied::new(format!(
|
||||||
|
"Connection to peer rejected: invalid multiaddr: {remote_addr}"
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.network_globals.peers.read().is_ip_banned(&ip) {
|
||||||
|
return Err(ConnectionDenied::new(format!(
|
||||||
|
"Connection to peer rejected: peer {ip} is banned"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_established_inbound_connection(
|
fn handle_established_inbound_connection(
|
||||||
&mut self,
|
&mut self,
|
||||||
_connection_id: ConnectionId,
|
_connection_id: ConnectionId,
|
||||||
_peer: PeerId,
|
peer_id: PeerId,
|
||||||
_local_addr: &libp2p::Multiaddr,
|
_local_addr: &libp2p::Multiaddr,
|
||||||
_remote_addr: &libp2p::Multiaddr,
|
remote_addr: &libp2p::Multiaddr,
|
||||||
) -> Result<libp2p::swarm::THandler<Self>, libp2p::swarm::ConnectionDenied> {
|
) -> Result<libp2p::swarm::THandler<Self>, ConnectionDenied> {
|
||||||
// TODO: we might want to check if we accept this peer or not in the future.
|
trace!(self.log, "Inbound connection"; "peer_id" => %peer_id, "multiaddr" => %remote_addr);
|
||||||
|
// We already checked if the peer was banned on `handle_pending_inbound_connection`.
|
||||||
|
if let Some(BanResult::BadScore) = self.ban_status(&peer_id) {
|
||||||
|
return Err(ConnectionDenied::new(
|
||||||
|
"Connection to peer rejected: peer has a bad score",
|
||||||
|
));
|
||||||
|
}
|
||||||
Ok(ConnectionHandler)
|
Ok(ConnectionHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_established_outbound_connection(
|
fn handle_established_outbound_connection(
|
||||||
&mut self,
|
&mut self,
|
||||||
_connection_id: ConnectionId,
|
_connection_id: ConnectionId,
|
||||||
_peer: PeerId,
|
peer_id: PeerId,
|
||||||
_addr: &libp2p::Multiaddr,
|
addr: &libp2p::Multiaddr,
|
||||||
_role_override: libp2p::core::Endpoint,
|
_role_override: libp2p::core::Endpoint,
|
||||||
) -> Result<libp2p::swarm::THandler<Self>, libp2p::swarm::ConnectionDenied> {
|
) -> Result<libp2p::swarm::THandler<Self>, libp2p::swarm::ConnectionDenied> {
|
||||||
// TODO: we might want to check if we accept this peer or not in the future.
|
trace!(self.log, "Outbound connection"; "peer_id" => %peer_id, "multiaddr" => %addr);
|
||||||
Ok(ConnectionHandler)
|
match self.ban_status(&peer_id) {
|
||||||
|
Some(cause) => {
|
||||||
|
error!(self.log, "Connected a banned peer. Rejecting connection"; "peer_id" => %peer_id);
|
||||||
|
Err(ConnectionDenied::new(cause))
|
||||||
|
}
|
||||||
|
None => Ok(ConnectionHandler),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,10 +254,7 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
|
|||||||
|
|
||||||
// increment prometheus metrics
|
// increment prometheus metrics
|
||||||
if self.metrics_enabled {
|
if self.metrics_enabled {
|
||||||
let remote_addr = match endpoint {
|
let remote_addr = endpoint.get_remote_address();
|
||||||
ConnectedPoint::Dialer { address, .. } => address,
|
|
||||||
ConnectedPoint::Listener { send_back_addr, .. } => send_back_addr,
|
|
||||||
};
|
|
||||||
match remote_addr.iter().find(|proto| {
|
match remote_addr.iter().find(|proto| {
|
||||||
matches!(
|
matches!(
|
||||||
proto,
|
proto,
|
||||||
@ -241,28 +277,6 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
|
|||||||
metrics::inc_counter(&metrics::PEER_CONNECT_EVENT_COUNT);
|
metrics::inc_counter(&metrics::PEER_CONNECT_EVENT_COUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to make sure the peer is not supposed to be banned
|
|
||||||
match self.ban_status(&peer_id) {
|
|
||||||
// TODO: directly emit the ban event?
|
|
||||||
BanResult::BadScore => {
|
|
||||||
// This is a faulty state
|
|
||||||
error!(self.log, "Connected to a banned peer. Re-banning"; "peer_id" => %peer_id);
|
|
||||||
// Disconnect the peer.
|
|
||||||
self.goodbye_peer(&peer_id, GoodbyeReason::Banned, ReportSource::PeerManager);
|
|
||||||
// Re-ban the peer to prevent repeated errors.
|
|
||||||
self.events.push(PeerManagerEvent::Banned(peer_id, vec![]));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BanResult::BannedIp(ip_addr) => {
|
|
||||||
// A good peer has connected to us via a banned IP address. We ban the peer and
|
|
||||||
// prevent future connections.
|
|
||||||
debug!(self.log, "Peer connected via banned IP. Banning"; "peer_id" => %peer_id, "banned_ip" => %ip_addr);
|
|
||||||
self.goodbye_peer(&peer_id, GoodbyeReason::BannedIP, ReportSource::PeerManager);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
BanResult::NotBanned => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count dialing peers in the limit if the peer dialed us.
|
// Count dialing peers in the limit if the peer dialed us.
|
||||||
let count_dialing = endpoint.is_listener();
|
let count_dialing = endpoint.is_listener();
|
||||||
// Check the connection limits
|
// Check the connection limits
|
||||||
@ -326,11 +340,7 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
|
|||||||
// reference so that peer manager can track this peer.
|
// reference so that peer manager can track this peer.
|
||||||
self.inject_disconnect(&peer_id);
|
self.inject_disconnect(&peer_id);
|
||||||
|
|
||||||
let remote_addr = match endpoint {
|
let remote_addr = endpoint.get_remote_address();
|
||||||
ConnectedPoint::Listener { send_back_addr, .. } => send_back_addr,
|
|
||||||
ConnectedPoint::Dialer { address, .. } => address,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update the prometheus metrics
|
// Update the prometheus metrics
|
||||||
if self.metrics_enabled {
|
if self.metrics_enabled {
|
||||||
match remote_addr.iter().find(|proto| {
|
match remote_addr.iter().find(|proto| {
|
||||||
|
@ -3,10 +3,13 @@ use peer_info::{ConnectionDirection, PeerConnectionStatus, PeerInfo};
|
|||||||
use rand::seq::SliceRandom;
|
use rand::seq::SliceRandom;
|
||||||
use score::{PeerAction, ReportSource, Score, ScoreState};
|
use score::{PeerAction, ReportSource, Score, ScoreState};
|
||||||
use slog::{crit, debug, error, trace, warn};
|
use slog::{crit, debug, error, trace, warn};
|
||||||
use std::cmp::Ordering;
|
|
||||||
use std::collections::{HashMap, HashSet};
|
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
use std::{cmp::Ordering, fmt::Display};
|
||||||
|
use std::{
|
||||||
|
collections::{HashMap, HashSet},
|
||||||
|
fmt::Formatter,
|
||||||
|
};
|
||||||
use sync_status::SyncStatus;
|
use sync_status::SyncStatus;
|
||||||
use types::EthSpec;
|
use types::EthSpec;
|
||||||
|
|
||||||
@ -136,26 +139,18 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the current [`BanResult`] of the peer. This doesn't check the connection state, rather the
|
/// Returns the current [`BanResult`] of the peer if banned. This doesn't check the connection state, rather the
|
||||||
/// underlying score of the peer. A peer may be banned but still in the connected state
|
/// underlying score of the peer. A peer may be banned but still in the connected state
|
||||||
/// temporarily.
|
/// temporarily.
|
||||||
///
|
///
|
||||||
/// This is used to determine if we should accept incoming connections or not.
|
/// This is used to determine if we should accept incoming connections or not.
|
||||||
pub fn ban_status(&self, peer_id: &PeerId) -> BanResult {
|
pub fn ban_status(&self, peer_id: &PeerId) -> Option<BanResult> {
|
||||||
if let Some(peer) = self.peers.get(peer_id) {
|
self.peers
|
||||||
match peer.score_state() {
|
.get(peer_id)
|
||||||
ScoreState::Banned => BanResult::BadScore,
|
.and_then(|peer| match peer.score_state() {
|
||||||
_ => {
|
ScoreState::Banned => Some(BanResult::BadScore),
|
||||||
if let Some(ip) = self.ip_is_banned(peer) {
|
_ => self.ip_is_banned(peer).map(BanResult::BannedIp),
|
||||||
BanResult::BannedIp(ip)
|
})
|
||||||
} else {
|
|
||||||
BanResult::NotBanned
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
BanResult::NotBanned
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if the peer's known addresses are currently banned.
|
/// Checks if the peer's known addresses are currently banned.
|
||||||
@ -1183,23 +1178,25 @@ pub enum BanOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// When checking if a peer is banned, it can be banned for multiple reasons.
|
/// When checking if a peer is banned, it can be banned for multiple reasons.
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum BanResult {
|
pub enum BanResult {
|
||||||
/// The peer's score is too low causing it to be banned.
|
/// The peer's score is too low causing it to be banned.
|
||||||
BadScore,
|
BadScore,
|
||||||
/// The peer should be banned because it is connecting from a banned IP address.
|
/// The peer should be banned because it is connecting from a banned IP address.
|
||||||
BannedIp(IpAddr),
|
BannedIp(IpAddr),
|
||||||
/// The peer is not banned.
|
|
||||||
NotBanned,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function for unit tests
|
impl Display for BanResult {
|
||||||
#[cfg(test)]
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
impl BanResult {
|
match self {
|
||||||
pub fn is_banned(&self) -> bool {
|
BanResult::BadScore => write!(f, "Peer has a bad score"),
|
||||||
!matches!(self, BanResult::NotBanned)
|
BanResult::BannedIp(addr) => write!(f, "Peer address: {} is banned", addr),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for BanResult {}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct BannedPeersCount {
|
pub struct BannedPeersCount {
|
||||||
/// The number of banned peers in the database.
|
/// The number of banned peers in the database.
|
||||||
@ -1852,11 +1849,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//check that ip1 and ip2 are banned but ip3-5 not
|
//check that ip1 and ip2 are banned but ip3-5 not
|
||||||
assert!(pdb.ban_status(&p1).is_banned());
|
assert!(pdb.ban_status(&p1).is_some());
|
||||||
assert!(pdb.ban_status(&p2).is_banned());
|
assert!(pdb.ban_status(&p2).is_some());
|
||||||
assert!(!pdb.ban_status(&p3).is_banned());
|
assert!(pdb.ban_status(&p3).is_none());
|
||||||
assert!(!pdb.ban_status(&p4).is_banned());
|
assert!(pdb.ban_status(&p4).is_none());
|
||||||
assert!(!pdb.ban_status(&p5).is_banned());
|
assert!(pdb.ban_status(&p5).is_none());
|
||||||
|
|
||||||
//ban also the last peer in peers
|
//ban also the last peer in peers
|
||||||
let _ = pdb.report_peer(
|
let _ = pdb.report_peer(
|
||||||
@ -1868,11 +1865,11 @@ mod tests {
|
|||||||
pdb.inject_disconnect(&peers[BANNED_PEERS_PER_IP_THRESHOLD + 1]);
|
pdb.inject_disconnect(&peers[BANNED_PEERS_PER_IP_THRESHOLD + 1]);
|
||||||
|
|
||||||
//check that ip1-ip4 are banned but ip5 not
|
//check that ip1-ip4 are banned but ip5 not
|
||||||
assert!(pdb.ban_status(&p1).is_banned());
|
assert!(pdb.ban_status(&p1).is_some());
|
||||||
assert!(pdb.ban_status(&p2).is_banned());
|
assert!(pdb.ban_status(&p2).is_some());
|
||||||
assert!(pdb.ban_status(&p3).is_banned());
|
assert!(pdb.ban_status(&p3).is_some());
|
||||||
assert!(pdb.ban_status(&p4).is_banned());
|
assert!(pdb.ban_status(&p4).is_some());
|
||||||
assert!(!pdb.ban_status(&p5).is_banned());
|
assert!(pdb.ban_status(&p5).is_none());
|
||||||
|
|
||||||
//peers[0] gets unbanned
|
//peers[0] gets unbanned
|
||||||
reset_score(&mut pdb, &peers[0]);
|
reset_score(&mut pdb, &peers[0]);
|
||||||
@ -1880,11 +1877,11 @@ mod tests {
|
|||||||
let _ = pdb.shrink_to_fit();
|
let _ = pdb.shrink_to_fit();
|
||||||
|
|
||||||
//nothing changed
|
//nothing changed
|
||||||
assert!(pdb.ban_status(&p1).is_banned());
|
assert!(pdb.ban_status(&p1).is_some());
|
||||||
assert!(pdb.ban_status(&p2).is_banned());
|
assert!(pdb.ban_status(&p2).is_some());
|
||||||
assert!(pdb.ban_status(&p3).is_banned());
|
assert!(pdb.ban_status(&p3).is_some());
|
||||||
assert!(pdb.ban_status(&p4).is_banned());
|
assert!(pdb.ban_status(&p4).is_some());
|
||||||
assert!(!pdb.ban_status(&p5).is_banned());
|
assert!(pdb.ban_status(&p5).is_none());
|
||||||
|
|
||||||
//peers[1] gets unbanned
|
//peers[1] gets unbanned
|
||||||
reset_score(&mut pdb, &peers[1]);
|
reset_score(&mut pdb, &peers[1]);
|
||||||
@ -1892,11 +1889,11 @@ mod tests {
|
|||||||
let _ = pdb.shrink_to_fit();
|
let _ = pdb.shrink_to_fit();
|
||||||
|
|
||||||
//all ips are unbanned
|
//all ips are unbanned
|
||||||
assert!(!pdb.ban_status(&p1).is_banned());
|
assert!(pdb.ban_status(&p1).is_none());
|
||||||
assert!(!pdb.ban_status(&p2).is_banned());
|
assert!(pdb.ban_status(&p2).is_none());
|
||||||
assert!(!pdb.ban_status(&p3).is_banned());
|
assert!(pdb.ban_status(&p3).is_none());
|
||||||
assert!(!pdb.ban_status(&p4).is_banned());
|
assert!(pdb.ban_status(&p4).is_none());
|
||||||
assert!(!pdb.ban_status(&p5).is_banned());
|
assert!(pdb.ban_status(&p5).is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1921,8 +1918,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check ip is banned
|
// check ip is banned
|
||||||
assert!(pdb.ban_status(&p1).is_banned());
|
assert!(pdb.ban_status(&p1).is_some());
|
||||||
assert!(!pdb.ban_status(&p2).is_banned());
|
assert!(pdb.ban_status(&p2).is_none());
|
||||||
|
|
||||||
// unban a peer
|
// unban a peer
|
||||||
reset_score(&mut pdb, &peers[0]);
|
reset_score(&mut pdb, &peers[0]);
|
||||||
@ -1930,8 +1927,8 @@ mod tests {
|
|||||||
let _ = pdb.shrink_to_fit();
|
let _ = pdb.shrink_to_fit();
|
||||||
|
|
||||||
// check not banned anymore
|
// check not banned anymore
|
||||||
assert!(!pdb.ban_status(&p1).is_banned());
|
assert!(pdb.ban_status(&p1).is_none());
|
||||||
assert!(!pdb.ban_status(&p2).is_banned());
|
assert!(pdb.ban_status(&p2).is_none());
|
||||||
|
|
||||||
// unban all peers
|
// unban all peers
|
||||||
for p in &peers {
|
for p in &peers {
|
||||||
@ -1950,8 +1947,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// both IP's are now banned
|
// both IP's are now banned
|
||||||
assert!(pdb.ban_status(&p1).is_banned());
|
assert!(pdb.ban_status(&p1).is_some());
|
||||||
assert!(pdb.ban_status(&p2).is_banned());
|
assert!(pdb.ban_status(&p2).is_some());
|
||||||
|
|
||||||
// unban all peers
|
// unban all peers
|
||||||
for p in &peers {
|
for p in &peers {
|
||||||
@ -1967,16 +1964,16 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// nothing is banned
|
// nothing is banned
|
||||||
assert!(!pdb.ban_status(&p1).is_banned());
|
assert!(pdb.ban_status(&p1).is_none());
|
||||||
assert!(!pdb.ban_status(&p2).is_banned());
|
assert!(pdb.ban_status(&p2).is_none());
|
||||||
|
|
||||||
// reban last peer
|
// reban last peer
|
||||||
let _ = pdb.report_peer(&peers[0], PeerAction::Fatal, ReportSource::PeerManager, "");
|
let _ = pdb.report_peer(&peers[0], PeerAction::Fatal, ReportSource::PeerManager, "");
|
||||||
pdb.inject_disconnect(&peers[0]);
|
pdb.inject_disconnect(&peers[0]);
|
||||||
|
|
||||||
//Ip's are banned again
|
//Ip's are banned again
|
||||||
assert!(pdb.ban_status(&p1).is_banned());
|
assert!(pdb.ban_status(&p1).is_some());
|
||||||
assert!(pdb.ban_status(&p2).is_banned());
|
assert!(pdb.ban_status(&p2).is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -20,8 +20,6 @@ where
|
|||||||
AppReqId: ReqId,
|
AppReqId: ReqId,
|
||||||
TSpec: EthSpec,
|
TSpec: EthSpec,
|
||||||
{
|
{
|
||||||
/// Peers banned.
|
|
||||||
pub banned_peers: libp2p::allow_block_list::Behaviour<libp2p::allow_block_list::BlockedPeers>,
|
|
||||||
/// Keep track of active and pending connections to enforce hard limits.
|
/// Keep track of active and pending connections to enforce hard limits.
|
||||||
pub connection_limits: libp2p::connection_limits::Behaviour,
|
pub connection_limits: libp2p::connection_limits::Behaviour,
|
||||||
/// The routing pub-sub mechanism for eth2.
|
/// The routing pub-sub mechanism for eth2.
|
||||||
|
@ -27,6 +27,7 @@ use gossipsub_scoring_parameters::{lighthouse_gossip_thresholds, PeerScoreSettin
|
|||||||
use libp2p::bandwidth::BandwidthSinks;
|
use libp2p::bandwidth::BandwidthSinks;
|
||||||
use libp2p::gossipsub::{
|
use libp2p::gossipsub::{
|
||||||
self, IdentTopic as Topic, MessageAcceptance, MessageAuthenticity, MessageId, PublishError,
|
self, IdentTopic as Topic, MessageAcceptance, MessageAuthenticity, MessageId, PublishError,
|
||||||
|
TopicScoreParams,
|
||||||
};
|
};
|
||||||
use libp2p::identify;
|
use libp2p::identify;
|
||||||
use libp2p::multiaddr::{Multiaddr, Protocol as MProtocol};
|
use libp2p::multiaddr::{Multiaddr, Protocol as MProtocol};
|
||||||
@ -353,11 +354,8 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
|
|||||||
libp2p::connection_limits::Behaviour::new(limits)
|
libp2p::connection_limits::Behaviour::new(limits)
|
||||||
};
|
};
|
||||||
|
|
||||||
let banned_peers = libp2p::allow_block_list::Behaviour::default();
|
|
||||||
|
|
||||||
let behaviour = {
|
let behaviour = {
|
||||||
Behaviour {
|
Behaviour {
|
||||||
banned_peers,
|
|
||||||
gossipsub,
|
gossipsub,
|
||||||
eth2_rpc,
|
eth2_rpc,
|
||||||
discovery,
|
discovery,
|
||||||
@ -637,6 +635,38 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove topic weight from all topics that don't have the given fork digest.
|
||||||
|
pub fn remove_topic_weight_except(&mut self, except: [u8; 4]) {
|
||||||
|
let new_param = TopicScoreParams {
|
||||||
|
topic_weight: 0.0,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
let subscriptions = self.network_globals.gossipsub_subscriptions.read().clone();
|
||||||
|
for topic in subscriptions
|
||||||
|
.iter()
|
||||||
|
.filter(|topic| topic.fork_digest != except)
|
||||||
|
{
|
||||||
|
let libp2p_topic: Topic = topic.clone().into();
|
||||||
|
match self
|
||||||
|
.gossipsub_mut()
|
||||||
|
.set_topic_params(libp2p_topic, new_param.clone())
|
||||||
|
{
|
||||||
|
Ok(_) => debug!(self.log, "Removed topic weight"; "topic" => %topic),
|
||||||
|
Err(e) => {
|
||||||
|
warn!(self.log, "Failed to remove topic weight"; "topic" => %topic, "error" => e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the scoring parameters for a topic if set.
|
||||||
|
pub fn get_topic_params(&self, topic: GossipTopic) -> Option<&TopicScoreParams> {
|
||||||
|
self.swarm
|
||||||
|
.behaviour()
|
||||||
|
.gossipsub
|
||||||
|
.get_topic_params(&topic.into())
|
||||||
|
}
|
||||||
|
|
||||||
/// Subscribes to a gossipsub topic.
|
/// Subscribes to a gossipsub topic.
|
||||||
///
|
///
|
||||||
/// Returns `true` if the subscription was successful and `false` otherwise.
|
/// Returns `true` if the subscription was successful and `false` otherwise.
|
||||||
@ -1445,15 +1475,10 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
|
|||||||
Some(NetworkEvent::PeerDisconnected(peer_id))
|
Some(NetworkEvent::PeerDisconnected(peer_id))
|
||||||
}
|
}
|
||||||
PeerManagerEvent::Banned(peer_id, associated_ips) => {
|
PeerManagerEvent::Banned(peer_id, associated_ips) => {
|
||||||
self.swarm.behaviour_mut().banned_peers.block_peer(peer_id);
|
|
||||||
self.discovery_mut().ban_peer(&peer_id, associated_ips);
|
self.discovery_mut().ban_peer(&peer_id, associated_ips);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
PeerManagerEvent::UnBanned(peer_id, associated_ips) => {
|
PeerManagerEvent::UnBanned(peer_id, associated_ips) => {
|
||||||
self.swarm
|
|
||||||
.behaviour_mut()
|
|
||||||
.banned_peers
|
|
||||||
.unblock_peer(peer_id);
|
|
||||||
self.discovery_mut().unban_peer(&peer_id, associated_ips);
|
self.discovery_mut().unban_peer(&peer_id, associated_ips);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -1502,7 +1527,6 @@ impl<AppReqId: ReqId, TSpec: EthSpec> Network<AppReqId, TSpec> {
|
|||||||
let maybe_event = match swarm_event {
|
let maybe_event = match swarm_event {
|
||||||
SwarmEvent::Behaviour(behaviour_event) => match behaviour_event {
|
SwarmEvent::Behaviour(behaviour_event) => match behaviour_event {
|
||||||
// Handle sub-behaviour events.
|
// Handle sub-behaviour events.
|
||||||
BehaviourEvent::BannedPeers(void) => void::unreachable(void),
|
|
||||||
BehaviourEvent::Gossipsub(ge) => self.inject_gs_event(ge),
|
BehaviourEvent::Gossipsub(ge) => self.inject_gs_event(ge),
|
||||||
BehaviourEvent::Eth2Rpc(re) => self.inject_rpc_event(re),
|
BehaviourEvent::Eth2Rpc(re) => self.inject_rpc_event(re),
|
||||||
// Inform the peer manager about discovered peers.
|
// Inform the peer manager about discovered peers.
|
||||||
|
@ -978,9 +978,17 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
|
|||||||
self.propagate_validation_result(message_id, peer_id, MessageAcceptance::Ignore);
|
self.propagate_validation_result(message_id, peer_id, MessageAcceptance::Ignore);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
Err(BlockError::BlockIsAlreadyKnown) => {
|
||||||
|
debug!(
|
||||||
|
self.log,
|
||||||
|
"Gossip block is already known";
|
||||||
|
"block_root" => %block_root,
|
||||||
|
);
|
||||||
|
self.propagate_validation_result(message_id, peer_id, MessageAcceptance::Ignore);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
Err(e @ BlockError::FutureSlot { .. })
|
Err(e @ BlockError::FutureSlot { .. })
|
||||||
| Err(e @ BlockError::WouldRevertFinalizedSlot { .. })
|
| Err(e @ BlockError::WouldRevertFinalizedSlot { .. })
|
||||||
| Err(e @ BlockError::BlockIsAlreadyKnown)
|
|
||||||
| Err(e @ BlockError::NotFinalizedDescendant { .. }) => {
|
| Err(e @ BlockError::NotFinalizedDescendant { .. }) => {
|
||||||
debug!(self.log, "Could not verify block for gossip. Ignoring the block";
|
debug!(self.log, "Could not verify block for gossip. Ignoring the block";
|
||||||
"error" => %e);
|
"error" => %e);
|
||||||
|
@ -215,15 +215,18 @@ pub struct NetworkService<T: BeaconChainTypes> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BeaconChainTypes> NetworkService<T> {
|
impl<T: BeaconChainTypes> NetworkService<T> {
|
||||||
#[allow(clippy::type_complexity)]
|
async fn build(
|
||||||
pub async fn start(
|
|
||||||
beacon_chain: Arc<BeaconChain<T>>,
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
config: &NetworkConfig,
|
config: &NetworkConfig,
|
||||||
executor: task_executor::TaskExecutor,
|
executor: task_executor::TaskExecutor,
|
||||||
gossipsub_registry: Option<&'_ mut Registry>,
|
gossipsub_registry: Option<&'_ mut Registry>,
|
||||||
beacon_processor_send: BeaconProcessorSend<T::EthSpec>,
|
beacon_processor_send: BeaconProcessorSend<T::EthSpec>,
|
||||||
beacon_processor_reprocess_tx: mpsc::Sender<ReprocessQueueMessage>,
|
beacon_processor_reprocess_tx: mpsc::Sender<ReprocessQueueMessage>,
|
||||||
) -> error::Result<(Arc<NetworkGlobals<T::EthSpec>>, NetworkSenders<T::EthSpec>)> {
|
) -> error::Result<(
|
||||||
|
NetworkService<T>,
|
||||||
|
Arc<NetworkGlobals<T::EthSpec>>,
|
||||||
|
NetworkSenders<T::EthSpec>,
|
||||||
|
)> {
|
||||||
let network_log = executor.log().clone();
|
let network_log = executor.log().clone();
|
||||||
// build the channels for external comms
|
// build the channels for external comms
|
||||||
let (network_senders, network_recievers) = NetworkSenders::new();
|
let (network_senders, network_recievers) = NetworkSenders::new();
|
||||||
@ -369,6 +372,28 @@ impl<T: BeaconChainTypes> NetworkService<T> {
|
|||||||
enable_light_client_server: config.enable_light_client_server,
|
enable_light_client_server: config.enable_light_client_server,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Ok((network_service, network_globals, network_senders))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
pub async fn start(
|
||||||
|
beacon_chain: Arc<BeaconChain<T>>,
|
||||||
|
config: &NetworkConfig,
|
||||||
|
executor: task_executor::TaskExecutor,
|
||||||
|
gossipsub_registry: Option<&'_ mut Registry>,
|
||||||
|
beacon_processor_send: BeaconProcessorSend<T::EthSpec>,
|
||||||
|
beacon_processor_reprocess_tx: mpsc::Sender<ReprocessQueueMessage>,
|
||||||
|
) -> error::Result<(Arc<NetworkGlobals<T::EthSpec>>, NetworkSenders<T::EthSpec>)> {
|
||||||
|
let (network_service, network_globals, network_senders) = Self::build(
|
||||||
|
beacon_chain,
|
||||||
|
config,
|
||||||
|
executor.clone(),
|
||||||
|
gossipsub_registry,
|
||||||
|
beacon_processor_send,
|
||||||
|
beacon_processor_reprocess_tx,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
network_service.spawn_service(executor);
|
network_service.spawn_service(executor);
|
||||||
|
|
||||||
Ok((network_globals, network_senders))
|
Ok((network_globals, network_senders))
|
||||||
@ -885,9 +910,10 @@ impl<T: BeaconChainTypes> NetworkService<T> {
|
|||||||
|
|
||||||
fn update_next_fork(&mut self) {
|
fn update_next_fork(&mut self) {
|
||||||
let new_enr_fork_id = self.beacon_chain.enr_fork_id();
|
let new_enr_fork_id = self.beacon_chain.enr_fork_id();
|
||||||
|
let new_fork_digest = new_enr_fork_id.fork_digest;
|
||||||
|
|
||||||
let fork_context = &self.fork_context;
|
let fork_context = &self.fork_context;
|
||||||
if let Some(new_fork_name) = fork_context.from_context_bytes(new_enr_fork_id.fork_digest) {
|
if let Some(new_fork_name) = fork_context.from_context_bytes(new_fork_digest) {
|
||||||
info!(
|
info!(
|
||||||
self.log,
|
self.log,
|
||||||
"Transitioned to new fork";
|
"Transitioned to new fork";
|
||||||
@ -910,6 +936,10 @@ impl<T: BeaconChainTypes> NetworkService<T> {
|
|||||||
Box::pin(next_fork_subscriptions_delay(&self.beacon_chain).into());
|
Box::pin(next_fork_subscriptions_delay(&self.beacon_chain).into());
|
||||||
self.next_unsubscribe = Box::pin(Some(tokio::time::sleep(unsubscribe_delay)).into());
|
self.next_unsubscribe = Box::pin(Some(tokio::time::sleep(unsubscribe_delay)).into());
|
||||||
info!(self.log, "Network will unsubscribe from old fork gossip topics in a few epochs"; "remaining_epochs" => UNSUBSCRIBE_DELAY_EPOCHS);
|
info!(self.log, "Network will unsubscribe from old fork gossip topics in a few epochs"; "remaining_epochs" => UNSUBSCRIBE_DELAY_EPOCHS);
|
||||||
|
|
||||||
|
// Remove topic weight from old fork topics to prevent peers that left on the mesh on
|
||||||
|
// old topics from being penalized for not sending us messages.
|
||||||
|
self.libp2p.remove_topic_weight_except(new_fork_digest);
|
||||||
} else {
|
} else {
|
||||||
crit!(self.log, "Unknown new enr fork id"; "new_fork_id" => ?new_enr_fork_id);
|
crit!(self.log, "Unknown new enr fork id"; "new_fork_id" => ?new_enr_fork_id);
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,26 @@ mod tests {
|
|||||||
use crate::persisted_dht::load_dht;
|
use crate::persisted_dht::load_dht;
|
||||||
use crate::{NetworkConfig, NetworkService};
|
use crate::{NetworkConfig, NetworkService};
|
||||||
use beacon_chain::test_utils::BeaconChainHarness;
|
use beacon_chain::test_utils::BeaconChainHarness;
|
||||||
use beacon_processor::BeaconProcessorChannels;
|
use beacon_chain::BeaconChainTypes;
|
||||||
use lighthouse_network::Enr;
|
use beacon_processor::{BeaconProcessorChannels, BeaconProcessorConfig};
|
||||||
|
use futures::StreamExt;
|
||||||
|
use lighthouse_network::types::{GossipEncoding, GossipKind};
|
||||||
|
use lighthouse_network::{Enr, GossipTopic};
|
||||||
use slog::{o, Drain, Level, Logger};
|
use slog::{o, Drain, Level, Logger};
|
||||||
use sloggers::{null::NullLoggerBuilder, Build};
|
use sloggers::{null::NullLoggerBuilder, Build};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
use types::MinimalEthSpec as E;
|
use types::{Epoch, EthSpec, ForkName, MinimalEthSpec, SubnetId};
|
||||||
|
|
||||||
|
impl<T: BeaconChainTypes> NetworkService<T> {
|
||||||
|
fn get_topic_params(
|
||||||
|
&self,
|
||||||
|
topic: GossipTopic,
|
||||||
|
) -> Option<&lighthouse_network::libp2p::gossipsub::TopicScoreParams> {
|
||||||
|
self.libp2p.get_topic_params(topic)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_logger(actual_log: bool) -> Logger {
|
fn get_logger(actual_log: bool) -> Logger {
|
||||||
if actual_log {
|
if actual_log {
|
||||||
@ -35,7 +47,7 @@ mod tests {
|
|||||||
fn test_dht_persistence() {
|
fn test_dht_persistence() {
|
||||||
let log = get_logger(false);
|
let log = get_logger(false);
|
||||||
|
|
||||||
let beacon_chain = BeaconChainHarness::builder(E)
|
let beacon_chain = BeaconChainHarness::builder(MinimalEthSpec)
|
||||||
.default_spec()
|
.default_spec()
|
||||||
.deterministic_keypairs(8)
|
.deterministic_keypairs(8)
|
||||||
.fresh_ephemeral_store()
|
.fresh_ephemeral_store()
|
||||||
@ -102,4 +114,126 @@ mod tests {
|
|||||||
"should have persisted the second ENR to store"
|
"should have persisted the second ENR to store"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test removing topic weight on old topics when a fork happens.
|
||||||
|
#[test]
|
||||||
|
fn test_removing_topic_weight_on_old_topics() {
|
||||||
|
let runtime = Arc::new(Runtime::new().unwrap());
|
||||||
|
|
||||||
|
// Capella spec
|
||||||
|
let mut spec = MinimalEthSpec::default_spec();
|
||||||
|
spec.altair_fork_epoch = Some(Epoch::new(0));
|
||||||
|
spec.bellatrix_fork_epoch = Some(Epoch::new(0));
|
||||||
|
spec.capella_fork_epoch = Some(Epoch::new(1));
|
||||||
|
|
||||||
|
// Build beacon chain.
|
||||||
|
let beacon_chain = BeaconChainHarness::builder(MinimalEthSpec)
|
||||||
|
.spec(spec.clone())
|
||||||
|
.deterministic_keypairs(8)
|
||||||
|
.fresh_ephemeral_store()
|
||||||
|
.mock_execution_layer()
|
||||||
|
.build()
|
||||||
|
.chain;
|
||||||
|
let (next_fork_name, _) = beacon_chain.duration_to_next_fork().expect("next fork");
|
||||||
|
assert_eq!(next_fork_name, ForkName::Capella);
|
||||||
|
|
||||||
|
// Build network service.
|
||||||
|
let (mut network_service, network_globals, _network_senders) = runtime.block_on(async {
|
||||||
|
let (_, exit) = exit_future::signal();
|
||||||
|
let (shutdown_tx, _) = futures::channel::mpsc::channel(1);
|
||||||
|
let executor = task_executor::TaskExecutor::new(
|
||||||
|
Arc::downgrade(&runtime),
|
||||||
|
exit,
|
||||||
|
get_logger(false),
|
||||||
|
shutdown_tx,
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut config = NetworkConfig::default();
|
||||||
|
config.set_ipv4_listening_address(std::net::Ipv4Addr::UNSPECIFIED, 21214, 21214, 21215);
|
||||||
|
config.discv5_config.table_filter = |_| true; // Do not ignore local IPs
|
||||||
|
config.upnp_enabled = false;
|
||||||
|
|
||||||
|
let beacon_processor_channels =
|
||||||
|
BeaconProcessorChannels::new(&BeaconProcessorConfig::default());
|
||||||
|
NetworkService::build(
|
||||||
|
beacon_chain.clone(),
|
||||||
|
&config,
|
||||||
|
executor.clone(),
|
||||||
|
None,
|
||||||
|
beacon_processor_channels.beacon_processor_tx,
|
||||||
|
beacon_processor_channels.work_reprocessing_tx,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Subscribe to the topics.
|
||||||
|
runtime.block_on(async {
|
||||||
|
while network_globals.gossipsub_subscriptions.read().len() < 2 {
|
||||||
|
if let Some(msg) = network_service.attestation_service.next().await {
|
||||||
|
network_service.on_attestation_service_msg(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Make sure the service is subscribed to the topics.
|
||||||
|
let (old_topic1, old_topic2) = {
|
||||||
|
let mut subnets = SubnetId::compute_subnets_for_epoch::<MinimalEthSpec>(
|
||||||
|
network_globals.local_enr().node_id().raw().into(),
|
||||||
|
beacon_chain.epoch().unwrap(),
|
||||||
|
&spec,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
assert_eq!(2, subnets.len());
|
||||||
|
|
||||||
|
let old_fork_digest = beacon_chain.enr_fork_id().fork_digest;
|
||||||
|
let old_topic1 = GossipTopic::new(
|
||||||
|
GossipKind::Attestation(subnets.pop().unwrap()),
|
||||||
|
GossipEncoding::SSZSnappy,
|
||||||
|
old_fork_digest,
|
||||||
|
);
|
||||||
|
let old_topic2 = GossipTopic::new(
|
||||||
|
GossipKind::Attestation(subnets.pop().unwrap()),
|
||||||
|
GossipEncoding::SSZSnappy,
|
||||||
|
old_fork_digest,
|
||||||
|
);
|
||||||
|
|
||||||
|
(old_topic1, old_topic2)
|
||||||
|
};
|
||||||
|
let subscriptions = network_globals.gossipsub_subscriptions.read().clone();
|
||||||
|
assert_eq!(2, subscriptions.len());
|
||||||
|
assert!(subscriptions.contains(&old_topic1));
|
||||||
|
assert!(subscriptions.contains(&old_topic2));
|
||||||
|
let old_topic_params1 = network_service
|
||||||
|
.get_topic_params(old_topic1.clone())
|
||||||
|
.expect("topic score params");
|
||||||
|
assert!(old_topic_params1.topic_weight > 0.0);
|
||||||
|
let old_topic_params2 = network_service
|
||||||
|
.get_topic_params(old_topic2.clone())
|
||||||
|
.expect("topic score params");
|
||||||
|
assert!(old_topic_params2.topic_weight > 0.0);
|
||||||
|
|
||||||
|
// Advance slot to the next fork
|
||||||
|
for _ in 0..MinimalEthSpec::slots_per_epoch() {
|
||||||
|
beacon_chain.slot_clock.advance_slot();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run `NetworkService::update_next_fork()`.
|
||||||
|
runtime.block_on(async {
|
||||||
|
network_service.update_next_fork();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check that topic_weight on the old topics has been zeroed.
|
||||||
|
let old_topic_params1 = network_service
|
||||||
|
.get_topic_params(old_topic1)
|
||||||
|
.expect("topic score params");
|
||||||
|
assert_eq!(0.0, old_topic_params1.topic_weight);
|
||||||
|
|
||||||
|
let old_topic_params2 = network_service
|
||||||
|
.get_topic_params(old_topic2)
|
||||||
|
.expect("topic score params");
|
||||||
|
assert_eq!(0.0, old_topic_params2.topic_weight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ use std::fmt::Debug;
|
|||||||
use std::fs;
|
use std::fs;
|
||||||
use std::net::Ipv6Addr;
|
use std::net::Ipv6Addr;
|
||||||
use std::net::{IpAddr, Ipv4Addr, ToSocketAddrs};
|
use std::net::{IpAddr, Ipv4Addr, ToSocketAddrs};
|
||||||
|
use std::num::NonZeroU16;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -1216,23 +1217,23 @@ pub fn set_network_config(
|
|||||||
if let Some(enr_udp_port_str) = cli_args.value_of("enr-udp-port") {
|
if let Some(enr_udp_port_str) = cli_args.value_of("enr-udp-port") {
|
||||||
config.enr_udp4_port = Some(
|
config.enr_udp4_port = Some(
|
||||||
enr_udp_port_str
|
enr_udp_port_str
|
||||||
.parse::<u16>()
|
.parse::<NonZeroU16>()
|
||||||
.map_err(|_| format!("Invalid discovery port: {}", enr_udp_port_str))?,
|
.map_err(|_| format!("Invalid ENR discovery port: {}", enr_udp_port_str))?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(enr_quic_port_str) = cli_args.value_of("enr-quic-port") {
|
if let Some(enr_quic_port_str) = cli_args.value_of("enr-quic-port") {
|
||||||
config.enr_quic4_port = Some(
|
config.enr_quic4_port = Some(
|
||||||
enr_quic_port_str
|
enr_quic_port_str
|
||||||
.parse::<u16>()
|
.parse::<NonZeroU16>()
|
||||||
.map_err(|_| format!("Invalid quic port: {}", enr_quic_port_str))?,
|
.map_err(|_| format!("Invalid ENR quic port: {}", enr_quic_port_str))?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(enr_tcp_port_str) = cli_args.value_of("enr-tcp-port") {
|
if let Some(enr_tcp_port_str) = cli_args.value_of("enr-tcp-port") {
|
||||||
config.enr_tcp4_port = Some(
|
config.enr_tcp4_port = Some(
|
||||||
enr_tcp_port_str
|
enr_tcp_port_str
|
||||||
.parse::<u16>()
|
.parse::<NonZeroU16>()
|
||||||
.map_err(|_| format!("Invalid ENR TCP port: {}", enr_tcp_port_str))?,
|
.map_err(|_| format!("Invalid ENR TCP port: {}", enr_tcp_port_str))?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1240,23 +1241,23 @@ pub fn set_network_config(
|
|||||||
if let Some(enr_udp_port_str) = cli_args.value_of("enr-udp6-port") {
|
if let Some(enr_udp_port_str) = cli_args.value_of("enr-udp6-port") {
|
||||||
config.enr_udp6_port = Some(
|
config.enr_udp6_port = Some(
|
||||||
enr_udp_port_str
|
enr_udp_port_str
|
||||||
.parse::<u16>()
|
.parse::<NonZeroU16>()
|
||||||
.map_err(|_| format!("Invalid discovery port: {}", enr_udp_port_str))?,
|
.map_err(|_| format!("Invalid ENR discovery port: {}", enr_udp_port_str))?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(enr_quic_port_str) = cli_args.value_of("enr-quic6-port") {
|
if let Some(enr_quic_port_str) = cli_args.value_of("enr-quic6-port") {
|
||||||
config.enr_quic6_port = Some(
|
config.enr_quic6_port = Some(
|
||||||
enr_quic_port_str
|
enr_quic_port_str
|
||||||
.parse::<u16>()
|
.parse::<NonZeroU16>()
|
||||||
.map_err(|_| format!("Invalid quic port: {}", enr_quic_port_str))?,
|
.map_err(|_| format!("Invalid ENR quic port: {}", enr_quic_port_str))?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(enr_tcp_port_str) = cli_args.value_of("enr-tcp6-port") {
|
if let Some(enr_tcp_port_str) = cli_args.value_of("enr-tcp6-port") {
|
||||||
config.enr_tcp6_port = Some(
|
config.enr_tcp6_port = Some(
|
||||||
enr_tcp_port_str
|
enr_tcp_port_str
|
||||||
.parse::<u16>()
|
.parse::<NonZeroU16>()
|
||||||
.map_err(|_| format!("Invalid ENR TCP port: {}", enr_tcp_port_str))?,
|
.map_err(|_| format!("Invalid ENR TCP port: {}", enr_tcp_port_str))?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1264,25 +1265,38 @@ pub fn set_network_config(
|
|||||||
if cli_args.is_present("enr-match") {
|
if cli_args.is_present("enr-match") {
|
||||||
// Match the IP and UDP port in the ENR.
|
// Match the IP and UDP port in the ENR.
|
||||||
|
|
||||||
// Set the ENR address to localhost if the address is unspecified.
|
|
||||||
if let Some(ipv4_addr) = config.listen_addrs().v4().cloned() {
|
if let Some(ipv4_addr) = config.listen_addrs().v4().cloned() {
|
||||||
|
// ensure the port is valid to be advertised
|
||||||
|
let disc_port = ipv4_addr
|
||||||
|
.disc_port
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| "enr-match can only be used with non-zero listening ports")?;
|
||||||
|
|
||||||
|
// Set the ENR address to localhost if the address is unspecified.
|
||||||
let ipv4_enr_addr = if ipv4_addr.addr == Ipv4Addr::UNSPECIFIED {
|
let ipv4_enr_addr = if ipv4_addr.addr == Ipv4Addr::UNSPECIFIED {
|
||||||
Ipv4Addr::LOCALHOST
|
Ipv4Addr::LOCALHOST
|
||||||
} else {
|
} else {
|
||||||
ipv4_addr.addr
|
ipv4_addr.addr
|
||||||
};
|
};
|
||||||
config.enr_address.0 = Some(ipv4_enr_addr);
|
config.enr_address.0 = Some(ipv4_enr_addr);
|
||||||
config.enr_udp4_port = Some(ipv4_addr.disc_port);
|
config.enr_udp4_port = Some(disc_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ipv6_addr) = config.listen_addrs().v6().cloned() {
|
if let Some(ipv6_addr) = config.listen_addrs().v6().cloned() {
|
||||||
|
// ensure the port is valid to be advertised
|
||||||
|
let disc_port = ipv6_addr
|
||||||
|
.disc_port
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| "enr-match can only be used with non-zero listening ports")?;
|
||||||
|
|
||||||
|
// Set the ENR address to localhost if the address is unspecified.
|
||||||
let ipv6_enr_addr = if ipv6_addr.addr == Ipv6Addr::UNSPECIFIED {
|
let ipv6_enr_addr = if ipv6_addr.addr == Ipv6Addr::UNSPECIFIED {
|
||||||
Ipv6Addr::LOCALHOST
|
Ipv6Addr::LOCALHOST
|
||||||
} else {
|
} else {
|
||||||
ipv6_addr.addr
|
ipv6_addr.addr
|
||||||
};
|
};
|
||||||
config.enr_address.1 = Some(ipv6_enr_addr);
|
config.enr_address.1 = Some(ipv6_enr_addr);
|
||||||
config.enr_udp6_port = Some(ipv6_addr.disc_port);
|
config.enr_udp6_port = Some(disc_port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,19 +60,25 @@ impl<T: EthSpec> BootNodeConfig<T> {
|
|||||||
|
|
||||||
// Set the Enr Discovery ports to the listening ports if not present.
|
// Set the Enr Discovery ports to the listening ports if not present.
|
||||||
if let Some(listening_addr_v4) = network_config.listen_addrs().v4() {
|
if let Some(listening_addr_v4) = network_config.listen_addrs().v4() {
|
||||||
network_config.enr_udp4_port = Some(
|
if network_config.enr_udp4_port.is_none() {
|
||||||
network_config
|
network_config.enr_udp4_port =
|
||||||
.enr_udp4_port
|
Some(network_config.enr_udp4_port.unwrap_or(
|
||||||
.unwrap_or(listening_addr_v4.disc_port),
|
listening_addr_v4.disc_port.try_into().map_err(|_| {
|
||||||
)
|
"boot node enr-udp-port not set and listening port is zero"
|
||||||
|
})?,
|
||||||
|
))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(listening_addr_v6) = network_config.listen_addrs().v6() {
|
if let Some(listening_addr_v6) = network_config.listen_addrs().v6() {
|
||||||
network_config.enr_udp6_port = Some(
|
if network_config.enr_udp6_port.is_none() {
|
||||||
network_config
|
network_config.enr_udp6_port =
|
||||||
.enr_udp6_port
|
Some(network_config.enr_udp6_port.unwrap_or(
|
||||||
.unwrap_or(listening_addr_v6.disc_port),
|
listening_addr_v6.disc_port.try_into().map_err(|_| {
|
||||||
)
|
"boot node enr-udp-port not set and listening port is zero"
|
||||||
|
})?,
|
||||||
|
))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// By default this is enabled. If it is not set, revert to false.
|
// By default this is enabled. If it is not set, revert to false.
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
status = [
|
status = [
|
||||||
"cargo-fmt",
|
|
||||||
"release-tests-ubuntu",
|
"release-tests-ubuntu",
|
||||||
"release-tests-windows",
|
"release-tests-windows",
|
||||||
"debug-tests-ubuntu",
|
"debug-tests-ubuntu",
|
||||||
@ -9,20 +8,16 @@ status = [
|
|||||||
"eth1-simulator-ubuntu",
|
"eth1-simulator-ubuntu",
|
||||||
"merge-transition-ubuntu",
|
"merge-transition-ubuntu",
|
||||||
"no-eth1-simulator-ubuntu",
|
"no-eth1-simulator-ubuntu",
|
||||||
"check-benchmarks",
|
"check-code",
|
||||||
"clippy",
|
|
||||||
"arbitrary-check",
|
|
||||||
"cargo-audit",
|
|
||||||
"cargo-udeps",
|
"cargo-udeps",
|
||||||
"beacon-chain-tests",
|
"beacon-chain-tests",
|
||||||
"op-pool-tests",
|
"op-pool-tests",
|
||||||
"doppelganger-protection-test",
|
"doppelganger-protection-test",
|
||||||
"execution-engine-integration-ubuntu",
|
"execution-engine-integration-ubuntu",
|
||||||
"cargo-vendor",
|
|
||||||
"check-msrv",
|
"check-msrv",
|
||||||
"slasher-tests",
|
"slasher-tests",
|
||||||
"syncing-simulator-ubuntu",
|
"syncing-simulator-ubuntu",
|
||||||
"compile-with-beta-compiler"
|
"compile-with-beta-compiler",
|
||||||
]
|
]
|
||||||
use_squash_merge = true
|
use_squash_merge = true
|
||||||
timeout_sec = 10800
|
timeout_sec = 10800
|
||||||
|
@ -9,8 +9,6 @@
|
|||||||
- enr:-Ku4QPn5eVhcoF1opaFEvg1b6JNFD2rqVkHQ8HApOKK61OIcIXD127bKWgAtbwI7pnxx6cDyk_nI88TrZKQaGMZj0q0Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDayLMaJc2VjcDI1NmsxoQK2sBOLGcUb4AwuYzFuAVCaNHA-dy24UuEKkeFNgCVCsIN1ZHCCIyg
|
- enr:-Ku4QPn5eVhcoF1opaFEvg1b6JNFD2rqVkHQ8HApOKK61OIcIXD127bKWgAtbwI7pnxx6cDyk_nI88TrZKQaGMZj0q0Bh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDayLMaJc2VjcDI1NmsxoQK2sBOLGcUb4AwuYzFuAVCaNHA-dy24UuEKkeFNgCVCsIN1ZHCCIyg
|
||||||
- enr:-Ku4QEWzdnVtXc2Q0ZVigfCGggOVB2Vc1ZCPEc6j21NIFLODSJbvNaef1g4PxhPwl_3kax86YPheFUSLXPRs98vvYsoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDZBrP2Jc2VjcDI1NmsxoQM6jr8Rb1ktLEsVcKAPa08wCsKUmvoQ8khiOl_SLozf9IN1ZHCCIyg
|
- enr:-Ku4QEWzdnVtXc2Q0ZVigfCGggOVB2Vc1ZCPEc6j21NIFLODSJbvNaef1g4PxhPwl_3kax86YPheFUSLXPRs98vvYsoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDZBrP2Jc2VjcDI1NmsxoQM6jr8Rb1ktLEsVcKAPa08wCsKUmvoQ8khiOl_SLozf9IN1ZHCCIyg
|
||||||
# Teku team (Consensys)
|
# Teku team (Consensys)
|
||||||
- enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2Gxb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNlY3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA
|
|
||||||
- enr:-KG4QL-eqFoHy0cI31THvtZjpYUu_Jdw_MO7skQRJxY1g5HTN1A0epPCU6vi0gLGUgrzpU-ygeMSS8ewVxDpKfYmxMMGhGV0aDKQtTA_KgAAAAD__________4JpZIJ2NIJpcIQ2_DUbiXNlY3AyNTZrMaED8GJ2vzUqgL6-KD1xalo1CsmY4X1HaDnyl6Y_WayCo9GDdGNwgiMog3VkcIIjKA
|
|
||||||
- enr:-KG4QMOEswP62yzDjSwWS4YEjtTZ5PO6r65CPqYBkgTTkrpaedQ8uEUo1uMALtJIvb2w_WWEVmg5yt1UAuK1ftxUU7QDhGV0aDKQu6TalgMAAAD__________4JpZIJ2NIJpcIQEnfA2iXNlY3AyNTZrMaEDfol8oLr6XJ7FsdAYE7lpJhKMls4G_v6qQOGKJUWGb_uDdGNwgiMog3VkcIIjKA
|
- enr:-KG4QMOEswP62yzDjSwWS4YEjtTZ5PO6r65CPqYBkgTTkrpaedQ8uEUo1uMALtJIvb2w_WWEVmg5yt1UAuK1ftxUU7QDhGV0aDKQu6TalgMAAAD__________4JpZIJ2NIJpcIQEnfA2iXNlY3AyNTZrMaEDfol8oLr6XJ7FsdAYE7lpJhKMls4G_v6qQOGKJUWGb_uDdGNwgiMog3VkcIIjKA
|
||||||
- enr:-KG4QF4B5WrlFcRhUU6dZETwY5ZzAXnA0vGC__L1Kdw602nDZwXSTs5RFXFIFUnbQJmhNGVU6OIX7KVrCSTODsz1tK4DhGV0aDKQu6TalgMAAAD__________4JpZIJ2NIJpcIQExNYEiXNlY3AyNTZrMaECQmM9vp7KhaXhI-nqL_R0ovULLCFSFTa9CPPSdb1zPX6DdGNwgiMog3VkcIIjKA
|
- enr:-KG4QF4B5WrlFcRhUU6dZETwY5ZzAXnA0vGC__L1Kdw602nDZwXSTs5RFXFIFUnbQJmhNGVU6OIX7KVrCSTODsz1tK4DhGV0aDKQu6TalgMAAAD__________4JpZIJ2NIJpcIQExNYEiXNlY3AyNTZrMaECQmM9vp7KhaXhI-nqL_R0ovULLCFSFTa9CPPSdb1zPX6DdGNwgiMog3VkcIIjKA
|
||||||
# Prysm team (Prysmatic Labs)
|
# Prysm team (Prysmatic Labs)
|
||||||
|
@ -6,3 +6,6 @@ edition = { workspace = true }
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
fnv = { workspace = true }
|
fnv = { workspace = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
mock_instant = "0.3"
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
//! This implements a time-based LRU cache for fast checking of duplicates
|
//! This implements a time-based LRU cache for fast checking of duplicates
|
||||||
use fnv::FnvHashSet;
|
use fnv::FnvHashSet;
|
||||||
|
#[cfg(test)]
|
||||||
|
use mock_instant::Instant;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::time::{Duration, Instant};
|
|
||||||
|
#[cfg(not(test))]
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
struct Element<Key> {
|
struct Element<Key> {
|
||||||
/// The key being inserted.
|
/// The key being inserted.
|
||||||
@ -222,16 +228,16 @@ mod test {
|
|||||||
cache.insert("a");
|
cache.insert("a");
|
||||||
cache.insert("b");
|
cache.insert("b");
|
||||||
|
|
||||||
std::thread::sleep(Duration::from_millis(20));
|
mock_instant::MockClock::advance(Duration::from_millis(20));
|
||||||
cache.insert("a");
|
cache.insert("a");
|
||||||
// a is newer now
|
// a is newer now
|
||||||
|
|
||||||
std::thread::sleep(Duration::from_millis(85));
|
mock_instant::MockClock::advance(Duration::from_millis(85));
|
||||||
assert!(cache.contains(&"a"),);
|
assert!(cache.contains(&"a"),);
|
||||||
// b was inserted first but was not as recent it should have been removed
|
// b was inserted first but was not as recent it should have been removed
|
||||||
assert!(!cache.contains(&"b"));
|
assert!(!cache.contains(&"b"));
|
||||||
|
|
||||||
std::thread::sleep(Duration::from_millis(16));
|
mock_instant::MockClock::advance(Duration::from_millis(16));
|
||||||
assert!(!cache.contains(&"a"));
|
assert!(!cache.contains(&"a"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#![cfg(all(test, not(feature = "fake_crypto")))]
|
#![cfg(all(test, not(feature = "fake_crypto"), not(debug_assertions)))]
|
||||||
|
|
||||||
use crate::per_block_processing::errors::{
|
use crate::per_block_processing::errors::{
|
||||||
AttestationInvalid, AttesterSlashingInvalid, BlockOperationError, BlockProcessingError,
|
AttestationInvalid, AttesterSlashingInvalid, BlockOperationError, BlockProcessingError,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::beacon_block_body::KzgCommitments;
|
use crate::beacon_block_body::KzgCommitments;
|
||||||
use crate::{
|
use crate::{
|
||||||
BlobRootsList, ChainSpec, EthSpec, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderDeneb,
|
BlobRootsList, ChainSpec, EthSpec, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderDeneb,
|
||||||
ExecutionPayloadHeaderMerge, ExecutionPayloadHeaderRef, ForkName, ForkVersionDeserialize,
|
ExecutionPayloadHeaderMerge, ExecutionPayloadHeaderRef, ExecutionPayloadHeaderRefMut, ForkName,
|
||||||
KzgProofs, SignedRoot, Uint256,
|
ForkVersionDeserialize, KzgProofs, SignedRoot, Uint256,
|
||||||
};
|
};
|
||||||
use bls::PublicKeyBytes;
|
use bls::PublicKeyBytes;
|
||||||
use bls::Signature;
|
use bls::Signature;
|
||||||
@ -26,7 +26,8 @@ pub struct BlindedBlobsBundle<E: EthSpec> {
|
|||||||
derive(PartialEq, Debug, Serialize, Deserialize, TreeHash, Clone),
|
derive(PartialEq, Debug, Serialize, Deserialize, TreeHash, Clone),
|
||||||
serde(bound = "E: EthSpec", deny_unknown_fields)
|
serde(bound = "E: EthSpec", deny_unknown_fields)
|
||||||
),
|
),
|
||||||
map_ref_into(ExecutionPayloadHeaderRef)
|
map_ref_into(ExecutionPayloadHeaderRef),
|
||||||
|
map_ref_mut_into(ExecutionPayloadHeaderRefMut)
|
||||||
)]
|
)]
|
||||||
#[derive(PartialEq, Debug, Serialize, Deserialize, TreeHash, Clone)]
|
#[derive(PartialEq, Debug, Serialize, Deserialize, TreeHash, Clone)]
|
||||||
#[serde(bound = "E: EthSpec", deny_unknown_fields, untagged)]
|
#[serde(bound = "E: EthSpec", deny_unknown_fields, untagged)]
|
||||||
@ -59,6 +60,14 @@ impl<'a, E: EthSpec> BuilderBidRef<'a, E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, E: EthSpec> BuilderBidRefMut<'a, E> {
|
||||||
|
pub fn header_mut(self) -> ExecutionPayloadHeaderRefMut<'a, E> {
|
||||||
|
map_builder_bid_ref_mut_into_execution_payload_header_ref_mut!(&'a _, self, |bid, cons| {
|
||||||
|
cons(&mut bid.header)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E: EthSpec> SignedRoot for BuilderBid<E> {}
|
impl<E: EthSpec> SignedRoot for BuilderBid<E> {}
|
||||||
|
|
||||||
/// Validator registration, for use in interacting with servers implementing the builder API.
|
/// Validator registration, for use in interacting with servers implementing the builder API.
|
||||||
|
@ -21,3 +21,17 @@ pub struct ValidatorRegistrationData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SignedRoot for ValidatorRegistrationData {}
|
impl SignedRoot for ValidatorRegistrationData {}
|
||||||
|
|
||||||
|
impl SignedValidatorRegistrationData {
|
||||||
|
pub fn verify_signature(&self, spec: &ChainSpec) -> bool {
|
||||||
|
self.message
|
||||||
|
.pubkey
|
||||||
|
.decompress()
|
||||||
|
.map(|pubkey| {
|
||||||
|
let domain = spec.get_builder_domain();
|
||||||
|
let message = self.message.signing_root(domain);
|
||||||
|
self.signature.verify(&pubkey, message)
|
||||||
|
})
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,16 +4,16 @@ use lighthouse_network::{
|
|||||||
libp2p::identity::secp256k1,
|
libp2p::identity::secp256k1,
|
||||||
NetworkConfig, NETWORK_KEY_FILENAME,
|
NetworkConfig, NETWORK_KEY_FILENAME,
|
||||||
};
|
};
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::{fs, net::Ipv4Addr};
|
use std::{fs, net::Ipv4Addr};
|
||||||
|
use std::{fs::File, num::NonZeroU16};
|
||||||
use types::{ChainSpec, EnrForkId, Epoch, EthSpec, Hash256};
|
use types::{ChainSpec, EnrForkId, Epoch, EthSpec, Hash256};
|
||||||
|
|
||||||
pub fn run<T: EthSpec>(matches: &ArgMatches) -> Result<(), String> {
|
pub fn run<T: EthSpec>(matches: &ArgMatches) -> Result<(), String> {
|
||||||
let ip: Ipv4Addr = clap_utils::parse_required(matches, "ip")?;
|
let ip: Ipv4Addr = clap_utils::parse_required(matches, "ip")?;
|
||||||
let udp_port: u16 = clap_utils::parse_required(matches, "udp-port")?;
|
let udp_port: NonZeroU16 = clap_utils::parse_required(matches, "udp-port")?;
|
||||||
let tcp_port: u16 = clap_utils::parse_required(matches, "tcp-port")?;
|
let tcp_port: NonZeroU16 = clap_utils::parse_required(matches, "tcp-port")?;
|
||||||
let output_dir: PathBuf = clap_utils::parse_required(matches, "output-dir")?;
|
let output_dir: PathBuf = clap_utils::parse_required(matches, "output-dir")?;
|
||||||
let genesis_fork_version: [u8; 4] =
|
let genesis_fork_version: [u8; 4] =
|
||||||
clap_utils::parse_ssz_required(matches, "genesis-fork-version")?;
|
clap_utils::parse_ssz_required(matches, "genesis-fork-version")?;
|
||||||
|
@ -22,9 +22,14 @@ use types::{
|
|||||||
Address, Checkpoint, Epoch, ExecutionBlockHash, ForkName, Hash256, MainnetEthSpec,
|
Address, Checkpoint, Epoch, ExecutionBlockHash, ForkName, Hash256, MainnetEthSpec,
|
||||||
ProgressiveBalancesMode,
|
ProgressiveBalancesMode,
|
||||||
};
|
};
|
||||||
use unused_port::{unused_tcp4_port, unused_tcp6_port, unused_udp4_port, unused_udp6_port};
|
|
||||||
|
|
||||||
const DEFAULT_ETH1_ENDPOINT: &str = "http://localhost:8545/";
|
const DEFAULT_ETH1_ENDPOINT: &str = "http://localhost:8545/";
|
||||||
|
const DUMMY_ENR_TCP_PORT: u16 = 7777;
|
||||||
|
const DUMMY_ENR_UDP_PORT: u16 = 8888;
|
||||||
|
const DUMMY_ENR_QUIC_PORT: u16 = 9999;
|
||||||
|
|
||||||
|
const _: () =
|
||||||
|
assert!(DUMMY_ENR_QUIC_PORT != 0 && DUMMY_ENR_TCP_PORT != 0 && DUMMY_ENR_UDP_PORT != 0);
|
||||||
|
|
||||||
/// Returns the `lighthouse beacon_node` command.
|
/// Returns the `lighthouse beacon_node` command.
|
||||||
fn base_cmd() -> Command {
|
fn base_cmd() -> Command {
|
||||||
@ -1036,7 +1041,7 @@ fn network_listen_address_flag_wrong_double_v6_value_config() {
|
|||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn network_port_flag_over_ipv4() {
|
fn network_port_flag_over_ipv4() {
|
||||||
let port = unused_tcp4_port().expect("Unable to find unused port.");
|
let port = 0;
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("port", Some(port.to_string().as_str()))
|
.flag("port", Some(port.to_string().as_str()))
|
||||||
.run()
|
.run()
|
||||||
@ -1053,7 +1058,7 @@ fn network_port_flag_over_ipv4() {
|
|||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn network_port_flag_over_ipv6() {
|
fn network_port_flag_over_ipv6() {
|
||||||
let port = unused_tcp6_port().expect("Unable to find unused port.");
|
let port = 0;
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("listen-address", Some("::1"))
|
.flag("listen-address", Some("::1"))
|
||||||
.flag("port", Some(port.to_string().as_str()))
|
.flag("port", Some(port.to_string().as_str()))
|
||||||
@ -1071,8 +1076,8 @@ fn network_port_flag_over_ipv6() {
|
|||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn network_port_and_discovery_port_flags_over_ipv4() {
|
fn network_port_and_discovery_port_flags_over_ipv4() {
|
||||||
let tcp4_port = unused_tcp4_port().expect("Unable to find unused port.");
|
let tcp4_port = 0;
|
||||||
let disc4_port = unused_udp4_port().expect("Unable to find unused port.");
|
let disc4_port = 0;
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("port", Some(tcp4_port.to_string().as_str()))
|
.flag("port", Some(tcp4_port.to_string().as_str()))
|
||||||
.flag("discovery-port", Some(disc4_port.to_string().as_str()))
|
.flag("discovery-port", Some(disc4_port.to_string().as_str()))
|
||||||
@ -1090,8 +1095,8 @@ fn network_port_and_discovery_port_flags_over_ipv4() {
|
|||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn network_port_and_discovery_port_flags_over_ipv6() {
|
fn network_port_and_discovery_port_flags_over_ipv6() {
|
||||||
let tcp6_port = unused_tcp6_port().expect("Unable to find unused port.");
|
let tcp6_port = 0;
|
||||||
let disc6_port = unused_udp6_port().expect("Unable to find unused port.");
|
let disc6_port = 0;
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("listen-address", Some("::1"))
|
.flag("listen-address", Some("::1"))
|
||||||
.flag("port", Some(tcp6_port.to_string().as_str()))
|
.flag("port", Some(tcp6_port.to_string().as_str()))
|
||||||
@ -1110,10 +1115,10 @@ fn network_port_and_discovery_port_flags_over_ipv6() {
|
|||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn network_port_and_discovery_port_flags_over_ipv4_and_ipv6() {
|
fn network_port_and_discovery_port_flags_over_ipv4_and_ipv6() {
|
||||||
let tcp4_port = unused_tcp4_port().expect("Unable to find unused port.");
|
let tcp4_port = 0;
|
||||||
let disc4_port = unused_udp4_port().expect("Unable to find unused port.");
|
let disc4_port = 0;
|
||||||
let tcp6_port = unused_tcp6_port().expect("Unable to find unused port.");
|
let tcp6_port = 0;
|
||||||
let disc6_port = unused_udp6_port().expect("Unable to find unused port.");
|
let disc6_port = 0;
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("listen-address", Some("::1"))
|
.flag("listen-address", Some("::1"))
|
||||||
.flag("listen-address", Some("127.0.0.1"))
|
.flag("listen-address", Some("127.0.0.1"))
|
||||||
@ -1145,12 +1150,12 @@ fn network_port_and_discovery_port_flags_over_ipv4_and_ipv6() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn network_port_discovery_quic_port_flags_over_ipv4_and_ipv6() {
|
fn network_port_discovery_quic_port_flags_over_ipv4_and_ipv6() {
|
||||||
let tcp4_port = unused_tcp4_port().expect("Unable to find unused port.");
|
let tcp4_port = 0;
|
||||||
let disc4_port = unused_udp4_port().expect("Unable to find unused port.");
|
let disc4_port = 0;
|
||||||
let quic4_port = unused_udp4_port().expect("Unable to find unused port.");
|
let quic4_port = 0;
|
||||||
let tcp6_port = unused_tcp6_port().expect("Unable to find unused port.");
|
let tcp6_port = 0;
|
||||||
let disc6_port = unused_udp6_port().expect("Unable to find unused port.");
|
let disc6_port = 0;
|
||||||
let quic6_port = unused_udp6_port().expect("Unable to find unused port.");
|
let quic6_port = 0;
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("listen-address", Some("::1"))
|
.flag("listen-address", Some("::1"))
|
||||||
.flag("listen-address", Some("127.0.0.1"))
|
.flag("listen-address", Some("127.0.0.1"))
|
||||||
@ -1226,7 +1231,7 @@ fn default_backfill_rate_limiting_flag() {
|
|||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn default_boot_nodes() {
|
fn default_boot_nodes() {
|
||||||
let number_of_boot_nodes = 17;
|
let number_of_boot_nodes = 15;
|
||||||
|
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.run_with_zero_port()
|
.run_with_zero_port()
|
||||||
@ -1296,57 +1301,91 @@ fn network_load_flag() {
|
|||||||
// Tests for ENR flags.
|
// Tests for ENR flags.
|
||||||
#[test]
|
#[test]
|
||||||
fn enr_udp_port_flag() {
|
fn enr_udp_port_flag() {
|
||||||
let port = unused_udp4_port().expect("Unable to find unused port.");
|
let port = DUMMY_ENR_UDP_PORT;
|
||||||
|
assert!(port != 0);
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("enr-udp-port", Some(port.to_string().as_str()))
|
.flag("enr-udp-port", Some(port.to_string().as_str()))
|
||||||
.run_with_zero_port()
|
.run_with_zero_port()
|
||||||
.with_config(|config| assert_eq!(config.network.enr_udp4_port, Some(port)));
|
.with_config(|config| {
|
||||||
|
assert_eq!(
|
||||||
|
config.network.enr_udp4_port.map(|port| port.get()),
|
||||||
|
Some(port)
|
||||||
|
)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn enr_quic_port_flag() {
|
fn enr_quic_port_flag() {
|
||||||
let port = unused_udp4_port().expect("Unable to find unused port.");
|
let port = DUMMY_ENR_QUIC_PORT;
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("enr-quic-port", Some(port.to_string().as_str()))
|
.flag("enr-quic-port", Some(port.to_string().as_str()))
|
||||||
.run_with_zero_port()
|
.run_with_zero_port()
|
||||||
.with_config(|config| assert_eq!(config.network.enr_quic4_port, Some(port)));
|
.with_config(|config| {
|
||||||
|
assert_eq!(
|
||||||
|
config.network.enr_quic4_port.map(|port| port.get()),
|
||||||
|
Some(port)
|
||||||
|
)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn enr_tcp_port_flag() {
|
fn enr_tcp_port_flag() {
|
||||||
let port = unused_tcp4_port().expect("Unable to find unused port.");
|
let port = DUMMY_ENR_TCP_PORT;
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("enr-tcp-port", Some(port.to_string().as_str()))
|
.flag("enr-tcp-port", Some(port.to_string().as_str()))
|
||||||
.run_with_zero_port()
|
.run_with_zero_port()
|
||||||
.with_config(|config| assert_eq!(config.network.enr_tcp4_port, Some(port)));
|
.with_config(|config| {
|
||||||
|
assert_eq!(
|
||||||
|
config.network.enr_tcp4_port.map(|port| port.get()),
|
||||||
|
Some(port)
|
||||||
|
)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn enr_udp6_port_flag() {
|
fn enr_udp6_port_flag() {
|
||||||
let port = unused_udp6_port().expect("Unable to find unused port.");
|
let port = DUMMY_ENR_UDP_PORT;
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("enr-udp6-port", Some(port.to_string().as_str()))
|
.flag("enr-udp6-port", Some(port.to_string().as_str()))
|
||||||
.run_with_zero_port()
|
.run_with_zero_port()
|
||||||
.with_config(|config| assert_eq!(config.network.enr_udp6_port, Some(port)));
|
.with_config(|config| {
|
||||||
|
assert_eq!(
|
||||||
|
config.network.enr_udp6_port.map(|port| port.get()),
|
||||||
|
Some(port)
|
||||||
|
)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn enr_quic6_port_flag() {
|
fn enr_quic6_port_flag() {
|
||||||
let port = unused_udp6_port().expect("Unable to find unused port.");
|
let port = DUMMY_ENR_QUIC_PORT;
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("enr-quic6-port", Some(port.to_string().as_str()))
|
.flag("enr-quic6-port", Some(port.to_string().as_str()))
|
||||||
.run_with_zero_port()
|
.run_with_zero_port()
|
||||||
.with_config(|config| assert_eq!(config.network.enr_quic6_port, Some(port)));
|
.with_config(|config| {
|
||||||
|
assert_eq!(
|
||||||
|
config.network.enr_quic6_port.map(|port| port.get()),
|
||||||
|
Some(port)
|
||||||
|
)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn enr_tcp6_port_flag() {
|
fn enr_tcp6_port_flag() {
|
||||||
let port = unused_tcp6_port().expect("Unable to find unused port.");
|
let port = DUMMY_ENR_TCP_PORT;
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("enr-tcp6-port", Some(port.to_string().as_str()))
|
.flag("enr-tcp6-port", Some(port.to_string().as_str()))
|
||||||
.run_with_zero_port()
|
.run_with_zero_port()
|
||||||
.with_config(|config| assert_eq!(config.network.enr_tcp6_port, Some(port)));
|
.with_config(|config| {
|
||||||
|
assert_eq!(
|
||||||
|
config.network.enr_tcp6_port.map(|port| port.get()),
|
||||||
|
Some(port)
|
||||||
|
)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn enr_match_flag_over_ipv4() {
|
fn enr_match_flag_over_ipv4() {
|
||||||
let addr = "127.0.0.2".parse::<Ipv4Addr>().unwrap();
|
let addr = "127.0.0.2".parse::<Ipv4Addr>().unwrap();
|
||||||
let udp4_port = unused_udp4_port().expect("Unable to find unused port.");
|
|
||||||
let tcp4_port = unused_tcp4_port().expect("Unable to find unused port.");
|
// the reason we use the ENR dummy values is because, due to the nature of the `--enr-match` flag, these will eventually become ENR ports (as well as listening ports).
|
||||||
|
let udp4_port = DUMMY_ENR_UDP_PORT;
|
||||||
|
let tcp4_port = DUMMY_ENR_TCP_PORT;
|
||||||
|
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("enr-match", None)
|
.flag("enr-match", None)
|
||||||
.flag("listen-address", Some("127.0.0.2"))
|
.flag("listen-address", Some("127.0.0.2"))
|
||||||
@ -1363,15 +1402,21 @@ fn enr_match_flag_over_ipv4() {
|
|||||||
Some((addr, udp4_port, tcp4_port))
|
Some((addr, udp4_port, tcp4_port))
|
||||||
);
|
);
|
||||||
assert_eq!(config.network.enr_address, (Some(addr), None));
|
assert_eq!(config.network.enr_address, (Some(addr), None));
|
||||||
assert_eq!(config.network.enr_udp4_port, Some(udp4_port));
|
assert_eq!(
|
||||||
|
config.network.enr_udp4_port.map(|port| port.get()),
|
||||||
|
Some(udp4_port)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn enr_match_flag_over_ipv6() {
|
fn enr_match_flag_over_ipv6() {
|
||||||
const ADDR: &str = "::1";
|
const ADDR: &str = "::1";
|
||||||
let addr = ADDR.parse::<Ipv6Addr>().unwrap();
|
let addr = ADDR.parse::<Ipv6Addr>().unwrap();
|
||||||
let udp6_port = unused_udp6_port().expect("Unable to find unused port.");
|
|
||||||
let tcp6_port = unused_tcp6_port().expect("Unable to find unused port.");
|
// the reason we use the ENR dummy values is because, due to the nature of the `--enr-match` flag, these will eventually become ENR ports (as well as listening ports).
|
||||||
|
let udp6_port = DUMMY_ENR_UDP_PORT;
|
||||||
|
let tcp6_port = DUMMY_ENR_TCP_PORT;
|
||||||
|
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("enr-match", None)
|
.flag("enr-match", None)
|
||||||
.flag("listen-address", Some(ADDR))
|
.flag("listen-address", Some(ADDR))
|
||||||
@ -1388,19 +1433,27 @@ fn enr_match_flag_over_ipv6() {
|
|||||||
Some((addr, udp6_port, tcp6_port))
|
Some((addr, udp6_port, tcp6_port))
|
||||||
);
|
);
|
||||||
assert_eq!(config.network.enr_address, (None, Some(addr)));
|
assert_eq!(config.network.enr_address, (None, Some(addr)));
|
||||||
assert_eq!(config.network.enr_udp6_port, Some(udp6_port));
|
assert_eq!(
|
||||||
|
config.network.enr_udp6_port.map(|port| port.get()),
|
||||||
|
Some(udp6_port)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn enr_match_flag_over_ipv4_and_ipv6() {
|
fn enr_match_flag_over_ipv4_and_ipv6() {
|
||||||
const IPV6_ADDR: &str = "::1";
|
const IPV6_ADDR: &str = "::1";
|
||||||
|
|
||||||
|
// the reason we use the ENR dummy values is because, due to the nature of the `--enr-match` flag, these will eventually become ENR ports (as well as listening ports).
|
||||||
|
let udp6_port = DUMMY_ENR_UDP_PORT;
|
||||||
|
let tcp6_port = DUMMY_ENR_TCP_PORT;
|
||||||
let ipv6_addr = IPV6_ADDR.parse::<Ipv6Addr>().unwrap();
|
let ipv6_addr = IPV6_ADDR.parse::<Ipv6Addr>().unwrap();
|
||||||
let udp6_port = unused_udp6_port().expect("Unable to find unused port.");
|
|
||||||
let tcp6_port = unused_tcp6_port().expect("Unable to find unused port.");
|
|
||||||
const IPV4_ADDR: &str = "127.0.0.1";
|
const IPV4_ADDR: &str = "127.0.0.1";
|
||||||
|
// the reason we use the ENR dummy values is because, due to the nature of the `--enr-match` flag, these will eventually become ENR ports (as well as listening ports).
|
||||||
|
let udp4_port = DUMMY_ENR_UDP_PORT;
|
||||||
|
let tcp4_port = DUMMY_ENR_TCP_PORT;
|
||||||
let ipv4_addr = IPV4_ADDR.parse::<Ipv4Addr>().unwrap();
|
let ipv4_addr = IPV4_ADDR.parse::<Ipv4Addr>().unwrap();
|
||||||
let udp4_port = unused_udp4_port().expect("Unable to find unused port.");
|
|
||||||
let tcp4_port = unused_tcp4_port().expect("Unable to find unused port.");
|
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("enr-match", None)
|
.flag("enr-match", None)
|
||||||
.flag("listen-address", Some(IPV4_ADDR))
|
.flag("listen-address", Some(IPV4_ADDR))
|
||||||
@ -1431,41 +1484,53 @@ fn enr_match_flag_over_ipv4_and_ipv6() {
|
|||||||
config.network.enr_address,
|
config.network.enr_address,
|
||||||
(Some(ipv4_addr), Some(ipv6_addr))
|
(Some(ipv4_addr), Some(ipv6_addr))
|
||||||
);
|
);
|
||||||
assert_eq!(config.network.enr_udp6_port, Some(udp6_port));
|
assert_eq!(
|
||||||
assert_eq!(config.network.enr_udp4_port, Some(udp4_port));
|
config.network.enr_udp6_port.map(|port| port.get()),
|
||||||
|
Some(udp6_port)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
config.network.enr_udp4_port.map(|port| port.get()),
|
||||||
|
Some(udp4_port)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn enr_address_flag_with_ipv4() {
|
fn enr_address_flag_with_ipv4() {
|
||||||
let addr = "192.167.1.1".parse::<Ipv4Addr>().unwrap();
|
let addr = "192.167.1.1".parse::<Ipv4Addr>().unwrap();
|
||||||
let port = unused_udp4_port().expect("Unable to find unused port.");
|
let port = DUMMY_ENR_UDP_PORT;
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("enr-address", Some("192.167.1.1"))
|
.flag("enr-address", Some("192.167.1.1"))
|
||||||
.flag("enr-udp-port", Some(port.to_string().as_str()))
|
.flag("enr-udp-port", Some(port.to_string().as_str()))
|
||||||
.run_with_zero_port()
|
.run_with_zero_port()
|
||||||
.with_config(|config| {
|
.with_config(|config| {
|
||||||
assert_eq!(config.network.enr_address, (Some(addr), None));
|
assert_eq!(config.network.enr_address, (Some(addr), None));
|
||||||
assert_eq!(config.network.enr_udp4_port, Some(port));
|
assert_eq!(
|
||||||
|
config.network.enr_udp4_port.map(|port| port.get()),
|
||||||
|
Some(port)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn enr_address_flag_with_ipv6() {
|
fn enr_address_flag_with_ipv6() {
|
||||||
let addr = "192.167.1.1".parse::<Ipv4Addr>().unwrap();
|
let addr = "192.167.1.1".parse::<Ipv4Addr>().unwrap();
|
||||||
let port = unused_udp4_port().expect("Unable to find unused port.");
|
let port = DUMMY_ENR_UDP_PORT;
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("enr-address", Some("192.167.1.1"))
|
.flag("enr-address", Some("192.167.1.1"))
|
||||||
.flag("enr-udp-port", Some(port.to_string().as_str()))
|
.flag("enr-udp-port", Some(port.to_string().as_str()))
|
||||||
.run_with_zero_port()
|
.run_with_zero_port()
|
||||||
.with_config(|config| {
|
.with_config(|config| {
|
||||||
assert_eq!(config.network.enr_address, (Some(addr), None));
|
assert_eq!(config.network.enr_address, (Some(addr), None));
|
||||||
assert_eq!(config.network.enr_udp4_port, Some(port));
|
assert_eq!(
|
||||||
|
config.network.enr_udp4_port.map(|port| port.get()),
|
||||||
|
Some(port)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn enr_address_dns_flag() {
|
fn enr_address_dns_flag() {
|
||||||
let addr = Ipv4Addr::LOCALHOST;
|
let addr = Ipv4Addr::LOCALHOST;
|
||||||
let ipv6addr = Ipv6Addr::LOCALHOST;
|
let ipv6addr = Ipv6Addr::LOCALHOST;
|
||||||
let port = unused_udp4_port().expect("Unable to find unused port.");
|
let port = DUMMY_ENR_UDP_PORT;
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("enr-address", Some("localhost"))
|
.flag("enr-address", Some("localhost"))
|
||||||
.flag("enr-udp-port", Some(port.to_string().as_str()))
|
.flag("enr-udp-port", Some(port.to_string().as_str()))
|
||||||
@ -1475,7 +1540,10 @@ fn enr_address_dns_flag() {
|
|||||||
config.network.enr_address.0 == Some(addr)
|
config.network.enr_address.0 == Some(addr)
|
||||||
|| config.network.enr_address.1 == Some(ipv6addr)
|
|| config.network.enr_address.1 == Some(ipv6addr)
|
||||||
);
|
);
|
||||||
assert_eq!(config.network.enr_udp4_port, Some(port));
|
assert_eq!(
|
||||||
|
config.network.enr_udp4_port.map(|port| port.get()),
|
||||||
|
Some(port)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
@ -1514,8 +1582,8 @@ fn http_address_ipv6_flag() {
|
|||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn http_port_flag() {
|
fn http_port_flag() {
|
||||||
let port1 = unused_tcp4_port().expect("Unable to find unused port.");
|
let port1 = 0;
|
||||||
let port2 = unused_tcp4_port().expect("Unable to find unused port.");
|
let port2 = 0;
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("http", None)
|
.flag("http", None)
|
||||||
.flag("http-port", Some(port1.to_string().as_str()))
|
.flag("http-port", Some(port1.to_string().as_str()))
|
||||||
@ -1671,8 +1739,8 @@ fn metrics_address_ipv6_flag() {
|
|||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn metrics_port_flag() {
|
fn metrics_port_flag() {
|
||||||
let port1 = unused_tcp4_port().expect("Unable to find unused port.");
|
let port1 = 0;
|
||||||
let port2 = unused_tcp4_port().expect("Unable to find unused port.");
|
let port2 = 0;
|
||||||
CommandLineTest::new()
|
CommandLineTest::new()
|
||||||
.flag("metrics", None)
|
.flag("metrics", None)
|
||||||
.flag("metrics-port", Some(port1.to_string().as_str()))
|
.flag("metrics-port", Some(port1.to_string().as_str()))
|
||||||
|
@ -66,8 +66,8 @@ impl<E: EthSpec> LocalNetwork<E> {
|
|||||||
BOOTNODE_PORT,
|
BOOTNODE_PORT,
|
||||||
QUIC_PORT,
|
QUIC_PORT,
|
||||||
);
|
);
|
||||||
beacon_config.network.enr_udp4_port = Some(BOOTNODE_PORT);
|
beacon_config.network.enr_udp4_port = Some(BOOTNODE_PORT.try_into().expect("non zero"));
|
||||||
beacon_config.network.enr_tcp4_port = Some(BOOTNODE_PORT);
|
beacon_config.network.enr_tcp4_port = Some(BOOTNODE_PORT.try_into().expect("non zero"));
|
||||||
beacon_config.network.discv5_config.table_filter = |_| true;
|
beacon_config.network.discv5_config.table_filter = |_| true;
|
||||||
|
|
||||||
let execution_node = if let Some(el_config) = &mut beacon_config.execution_layer {
|
let execution_node = if let Some(el_config) = &mut beacon_config.execution_layer {
|
||||||
@ -152,14 +152,16 @@ impl<E: EthSpec> LocalNetwork<E> {
|
|||||||
.expect("bootnode must have a network"),
|
.expect("bootnode must have a network"),
|
||||||
);
|
);
|
||||||
let count = (self.beacon_node_count() + self.proposer_node_count()) as u16;
|
let count = (self.beacon_node_count() + self.proposer_node_count()) as u16;
|
||||||
|
let libp2p_tcp_port = BOOTNODE_PORT + count;
|
||||||
|
let discv5_port = BOOTNODE_PORT + count;
|
||||||
beacon_config.network.set_ipv4_listening_address(
|
beacon_config.network.set_ipv4_listening_address(
|
||||||
std::net::Ipv4Addr::UNSPECIFIED,
|
std::net::Ipv4Addr::UNSPECIFIED,
|
||||||
BOOTNODE_PORT + count,
|
libp2p_tcp_port,
|
||||||
BOOTNODE_PORT + count,
|
discv5_port,
|
||||||
QUIC_PORT + count,
|
QUIC_PORT + count,
|
||||||
);
|
);
|
||||||
beacon_config.network.enr_udp4_port = Some(BOOTNODE_PORT + count);
|
beacon_config.network.enr_udp4_port = Some(discv5_port.try_into().unwrap());
|
||||||
beacon_config.network.enr_tcp4_port = Some(BOOTNODE_PORT + count);
|
beacon_config.network.enr_tcp4_port = Some(libp2p_tcp_port.try_into().unwrap());
|
||||||
beacon_config.network.discv5_config.table_filter = |_| true;
|
beacon_config.network.discv5_config.table_filter = |_| true;
|
||||||
beacon_config.network.proposer_only = is_proposer;
|
beacon_config.network.proposer_only = is_proposer;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
openssl req -x509 -sha256 -nodes -days 36500 -newkey rsa:4096 -keyout web3signer/key.key -out web3signer/cert.pem -config web3signer/config &&
|
openssl req -x509 -sha256 -nodes -days 36500 -newkey rsa:4096 -keyout web3signer/key.key -out web3signer/cert.pem -config web3signer/config &&
|
||||||
openssl pkcs12 -export -out web3signer/key.p12 -inkey web3signer/key.key -in web3signer/cert.pem -password pass:$(cat web3signer/password.txt) &&
|
openssl pkcs12 -export -aes256 -out web3signer/key.p12 -inkey web3signer/key.key -in web3signer/cert.pem -password pass:$(cat web3signer/password.txt) &&
|
||||||
cp web3signer/cert.pem lighthouse/web3signer.pem &&
|
cp web3signer/cert.pem lighthouse/web3signer.pem &&
|
||||||
openssl req -x509 -sha256 -nodes -days 36500 -newkey rsa:4096 -keyout lighthouse/key.key -out lighthouse/cert.pem -config lighthouse/config &&
|
openssl req -x509 -sha256 -nodes -days 36500 -newkey rsa:4096 -keyout lighthouse/key.key -out lighthouse/cert.pem -config lighthouse/config &&
|
||||||
openssl pkcs12 -export -out lighthouse/key.p12 -inkey lighthouse/key.key -in lighthouse/cert.pem -password pass:$(cat lighthouse/password.txt) &&
|
openssl pkcs12 -export -aes256 -out lighthouse/key.p12 -inkey lighthouse/key.key -in lighthouse/cert.pem -password pass:$(cat lighthouse/password.txt) &&
|
||||||
openssl x509 -noout -fingerprint -sha256 -inform pem -in lighthouse/cert.pem | cut -b 20-| sed "s/^/lighthouse /" > web3signer/known_clients.txt
|
openssl x509 -noout -fingerprint -sha256 -inform pem -in lighthouse/cert.pem | cut -b 20-| sed "s/^/lighthouse /" > web3signer/known_clients.txt
|
||||||
|
@ -1,33 +1,33 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIFujCCA6KgAwIBAgIUELASgYwStCn/u/8tPByRADyCwLEwDQYJKoZIhvcNAQEL
|
MIIFujCCA6KgAwIBAgIUXZijYo8W4/9dAq58ocFEbZDxohwwDQYJKoZIhvcNAQEL
|
||||||
BQAwazELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMREwDwYDVQQHDAhTb21lQ2l0
|
BQAwazELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMREwDwYDVQQHDAhTb21lQ2l0
|
||||||
eTESMBAGA1UECgwJTXlDb21wYW55MRMwEQYDVQQLDApNeURpdmlzaW9uMRMwEQYD
|
eTESMBAGA1UECgwJTXlDb21wYW55MRMwEQYDVQQLDApNeURpdmlzaW9uMRMwEQYD
|
||||||
VQQDDApsaWdodGhvdXNlMCAXDTIzMDkyMjAzMDA1N1oYDzIxMjMwODI5MDMwMDU3
|
VQQDDApsaWdodGhvdXNlMCAXDTIzMDkyMDAyNTYzNloYDzIxMjMwODI3MDI1NjM2
|
||||||
WjBrMQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkExETAPBgNVBAcMCFNvbWVDaXR5
|
WjBrMQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkExETAPBgNVBAcMCFNvbWVDaXR5
|
||||||
MRIwEAYDVQQKDAlNeUNvbXBhbnkxEzARBgNVBAsMCk15RGl2aXNpb24xEzARBgNV
|
MRIwEAYDVQQKDAlNeUNvbXBhbnkxEzARBgNVBAsMCk15RGl2aXNpb24xEzARBgNV
|
||||||
BAMMCmxpZ2h0aG91c2UwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCc
|
BAMMCmxpZ2h0aG91c2UwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC1
|
||||||
i30cib5B/B5QNd8grzi4LxmlyfZFi3VfpukwdwOD1Xk3ODk1OtjAzhK46YhDclvc
|
R1M9NnRwUsqFvJzNWPKuY1PW7llwRRWCixiWNvcxukGTa6AMLZDrYO1Y7qlw5m52
|
||||||
u98m1Dnib1Z+eTjRuEEoekIxz2+BbOle7G52LNvuDZpD+HKucqIU3TnEKPPuTYPp
|
aHSA2fs2KyeA61yajG/BsLn1vmTtJMZXgLsG0MIqvhgOoh+ZZbl8biO0gQJSRSDE
|
||||||
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
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
@ -1,52 +1,52 @@
|
|||||||
-----BEGIN PRIVATE KEY-----
|
-----BEGIN PRIVATE KEY-----
|
||||||
MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQCci30cib5B/B5Q
|
MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQC1R1M9NnRwUsqF
|
||||||
Nd8grzi4LxmlyfZFi3VfpukwdwOD1Xk3ODk1OtjAzhK46YhDclvcu98m1Dnib1Z+
|
vJzNWPKuY1PW7llwRRWCixiWNvcxukGTa6AMLZDrYO1Y7qlw5m52aHSA2fs2KyeA
|
||||||
eTjRuEEoekIxz2+BbOle7G52LNvuDZpD+HKucqIU3TnEKPPuTYPplZ1n/9EyxXUw
|
61yajG/BsLn1vmTtJMZXgLsG0MIqvhgOoh+ZZbl8biO0gQJSRSDEjf0ogUVM9TCE
|
||||||
D5uTkn7xXzK8UFXUt73j6I6VFMdHlNcwLcx8KSwBDzvnGT4ew/UL+ThON3j5rIT+
|
t6ydbGnzgs8EESqvyXcreaXfmLI7jiX/BkwCdf+Ru+H3MF96QgAwOz1d8/fxYJvI
|
||||||
nFHDcC2zoM+6ANdVkL6GHid4/cOcYW6GxB9TRZtEasqze41bC+kXZtPlV5V2nilA
|
pT/DOx4NuMZouSAcUVXgwcVb6JXeTg0xVcL33lluquhYDR0gD5FeV0fPth+e9XMA
|
||||||
zVj8z9ynwBpHkLH+E6sMUhSEwA++QfI1gGf0FmSBgSIZ3RdPo/dphkLG8fZXKMkM
|
H7udim8E5wn2Ep8CAVoeVq6K9mBM3NqP7+2YmU//jLbkd6UvKPaI0vps1zF9Bo8Q
|
||||||
zKkRm5hcstDP6DnTIYl+CfuVez5gZ0/yelAqXNvTqMKuDhHTTRRYaOXZX4BAiQO2
|
ewiRbM0IRse99ikCVZcjOcZSitw3kwTg59NjZ0Vk9R/2YQt/gGWMVcR//EtbOZGq
|
||||||
Q6a6WYLe87E2ka5AF2T2y/BPeXjUwDS/1mFIB3FUGlMLVJt8/RLznXVGoSsYaptt
|
zGrLPFKOcWO85Ggz746Saj15N+bqT20hXHyiwYL8DLgJkMR2W9Nr67Vyi9SWSM6r
|
||||||
iiPucQbMPEysCJ4/LZ9zxe3EDWWjpurLHGi/Y/dVziEvg1EoycixdZogKz0QVCz4
|
dRQlezlHq/yNEh+JuY7eoC3VeVw9K1ZXP+OKAwbpcnvd3uLwV91fkpT6kjc6d2h4
|
||||||
++QI0kPDDX7So7CWni2JJuYguF/8CX8QbCT2L8jXf0uQrq76FLKj88A7lS8DzXBt
|
bK8fhvF16Em42JypQCl0xMhgg/8MFO+6ZLy5otWAdsSYyO5k9CAa3zLeqd89dS7H
|
||||||
/pRryiIlDyLenJwHmrv6p+P/FYvgnJHvAEtTynxYm5GA16YWy+Djc5XVgNHjV4Td
|
NLdLZ0Y5SFWm6y5Kqu89ErIENafX5DxupHWsruiBV7zhDHNPaGcfTPFe8xuDYsi1
|
||||||
X3GueAp+NhBBaHDFvYCbP/oXkRvNRQIDAQABAoICACCSBxxeblblQVtX8g4nVso/
|
55veOfEiDh4g+X1qjL8x8OEDjgsM3QIDAQABAoICAEP5a1KMPUwzF0Lfr1Jm1JUk
|
||||||
hnsPi61JiEi3/hGG2ZTe4AMEsCZqkXmABrYxZJf/3awN7K5z/n0lxB25VACScQAe
|
pLb26C2rkf3B56XIFZgddeJwHHMEkQ9Z6JYM5Bd0KJ6Y23rHgiXVN7plRvOiznMs
|
||||||
e9JIQf9wLRgCYjM1PycG7n9Q3G9+S0nDA4dUK/h7aUQ6zE68k4aYPbsbrDdmhgHr
|
MAbgblroC8GbAUZ0eCJr5nxyOXQdS1jHufbA21x7FGbvsSqDkrdhR2C0uPLMyMvp
|
||||||
WC+FGW6SMjCOjMfo1FOI3MLZ7I8ys8Seqkx5XIrjI4NzvWrMsN9lrSAaXwqmNuQG
|
VHP7dey1mEyCkHrP+KFRU5kVxOG1WnBMqdY1Ws/uuMBdLk0xItttdOzfXhH4dHQD
|
||||||
Q+ID1cmoPXPDJ1xNlBrfzLK+cHQPafAwte7k+HKmhj9HtjOj5uWQn62ra+Xhy5ud
|
wc5aAJrtusyNDFLC25Og49yIgpPMWe+gAYCm5jFz9PgRtVlDOwcxlX5J5+GSm7+U
|
||||||
ZPpZ2Savaem81CcQnNXte5r1Fevbktq9Bt7RuM1ppIrwk8k3w5S72CTRGiYfNPJV
|
XM1bPSmU1TSEH233JbQcqo4HkynB71ftbVUtMhEFhLBYoFO4u5Ncpr+wys0xJY4f
|
||||||
M1RMp46GrXVJdmx3k9LQfKdT6Gv9xTJXYQl7jN0+4uZ7QrVQHpcMpxPsATl+cQQH
|
3aJRV5+gtlmAmsKN66GoMA10KNlLp2z7XMlx1EXegOHthcKfgf5D6LKRz8qZhknm
|
||||||
wzCTbj2Oqn/30KqkZLyueN2MalRP8mVSe5nD+vvGb/sWLs52kp6QvHdlXER2RBFk
|
FFgAOg9Bak1mt1DighhPUJ0vLYU6K+u0ZXwysYygOkBJ/yj63ApuPCSTQb7U0JlL
|
||||||
tJ5cGi+vgueoukb+qatiAE2y5MxYCqD02ShGcLos/SUQThRhL+iD8t0h+FoPTD5y
|
JMgesy1om3rVdN0Oc7hNaxq7VwswkzUTUKS2ZvGozF3MmdPHNm5weJTb3NsWv8Qo
|
||||||
eTNZ85hF1HdypH1If8/YGETg55+fHYUAtYGT6R8lYeFMvBC05suorLBciXShOGuY
|
HiK1I88tY9oZ5r91SC82hMErmG4ElXFLxic1B29h3fsIe/l+WjmZRXixD9ugV0gj
|
||||||
4zBbt32fPlsXlLneAtAAFv2BiJMt0TQavWHITLInFW1/aMHDV4/Pq69sRZuHdRaW
|
CvNa8QD9K3hljlNrR6eSXeO2QOyxAEUr2N1MBlxrnAWZCzXKiTvTx1aKDYhJT0DY
|
||||||
XFXD8CjnPUS5tBMQOqYhAoIBAQDLqUo7v3SpIstXmyU7BfUBuTYGS7MzjMhDxFUl
|
zae/etTLHVjzgdH6GS33AoIBAQDaaWYHa9wkJIJPX4siVCatwWKGTjVfDb5Q9upf
|
||||||
HvmbVZlOXhnPb3p4mW/XHrah9CjFBLJt3CF+PP/njwMw0YtPxCQpQwj0pI8CuveE
|
twkxCf58pmbzUOXW3dbaz6S0npR0V6Wqh3S8HW7xaHgDZDMLJ1WxLJrgqDKU3Pqc
|
||||||
4Puq2wEfxVg+JKh1xidNj8230/WINzwfLCVfco7KKmjQX0MgMGaANQ0sGnt/r1eB
|
k7xnA/krWqoRVSOOGkPnSrnZo6AVc6FR+iwJjfuUu0rFDwiyuqvuXpwNsVwvAOoL
|
||||||
MwpY5uID+D5PORXUcHxBWlsVLyzZ9ZqKhAgewr3i7BLX2y7nwqEGlWTt1lxzZGCR
|
xIbaEbGUHiFsZamm2YkoxrEjXGFkZxQX9+n9f+IAiMxMQc0wezRREc8e61/mTovJ
|
||||||
a8NZIAIs3qGzAgtm7O3hMz6XZulVyVSrMmmT8qXT4Lo1nW/9J6slV7Wdp9f++mr9
|
QJ7ZDd7zLUR7Yeqciy59NOsD57cGtnp1K28I2eKLA4taghgd5bJjPkUaHg9j5Xf6
|
||||||
m2vwrpJtmdPcA+YKPVgoFlKmZpZZbVvd+4uy8ksoxs1/cF7VAoIBAQDExnLQplq2
|
nsxU2QCp9kpwXvtMxN7pERKWFsnmu8tfJOiUWCpp8SLbIl6nAoIBAQDUefKKjRLa
|
||||||
BPoxEDAnlS+8Jju5en5Pk70HOfpQGUa4/6vY60x/N5sJqc6CcDySkkxRI8jLzMTe
|
6quNW0rOGn2kx0K6sG7T45OhwvWXVjnPAjX3/2mAMALT1wc3t0iKDvpIEfMadW2S
|
||||||
AE9jqM+Z39MvGCH+SF9EPRopbAJIrcChXfvk2Imp7PLFRGrEBju63nQfaHdcefFy
|
O8x2FwyifdJXmkz943EZ/J5Tq1H0wr4NeClX4UlPIAx3CdFlCphqH6QfKtrpQ+Hf
|
||||||
Ia7RA8SCHLCReRdqPjSXbPAYPZK84vVNSfhrkytA4FJnaojvaqJqLQH9vB7CXv18
|
+e8XzjVvdg8Y/RcbWgPgBtOh2oKT5QHDh13/994nH7GhVM7PjLUVvZVmNWaC77zr
|
||||||
Fu6w5fnrgARIoBhy2mb0QWzgd9JMsVDgS5XyX/4HBUejjXDdmLosOZ4PJ0GM2+tr
|
bXcvJFF/81PAPWC2JoV6TL/CXvda2tG2clxbSfykfUBPBpeyEijMoxC4UMuCHhbp
|
||||||
ilO/9KKhV9lqH7DcFgJBNkgVKRD1Ijr21yyOkttB5PULzaTQhzqkorGkWgyTzLWn
|
NpLfKJQp9XNqbBG2K4jgLQ8Ipk6Vtia/hktLgORf/pbQ4PxEv7OP5e1AOreDg/CW
|
||||||
ksqOr2cWt0yxAoIBAElIazvAkpvht0WYv/bTF+w81uHBD4R3HgC0fubSlIJ+dKGs
|
RnQtBb+/8czbAoIBABfDA8Cm8WpVNoAgKujvMs4QjgGCnLfcrOnuEw2awjs9lRxG
|
||||||
XqEzvd/zZjkEBjeUga8TF5lMYojoLjUGUuGYJQbYzyJBytEs/YDAAhzAUA6Uq3zh
|
lki+cmLv+6IOmSK1Zf1KU9G7ru2QXjORZA0qZ4s9GkuOSMNMSUR8zh8ey46Bligr
|
||||||
J/WEf1GRscbI/f8tt+YB6hJVckU8FYFNbVW9UYwdnmR3snuyM8ooL9Z/pTOEMMO4
|
UvlTw+x/2wdcz99nt9DdpZ1flE7tzYMe5UGPIykeufnS/TNYKmlKtivVk75B0ooE
|
||||||
6cLcCazdpPhnKOsghIURSUCabcmTzXv/8m/VoLUoZYTW8PBb9/xVnCH3ot1JFT9M
|
xSof3Vczr4JqK3dnY4ki1cLNy/0yXookV+Wr+wDdRpHTWC9K+EH8JaUdjKqcobbf
|
||||||
BOdCzxOEIbytEdKs5z1FKsBHbZIc9+qbrKVqN0fipETVoLZQFPrc5O7IpDiAuJPT
|
I+Ywfu/NDJ++lBr2qKjoTWZV9VyHJ+hr2Etef/Uwujml2qq+vnnlyynPAPfyK+pR
|
||||||
jFZY2MfKdxRFpAvYUjVvkmT4BLapVL4hewRmTNkCggEBAKuJP8/KJSulvSEGNqRa
|
y0NycfCmMoI0w0rk685YfAW75DnPZb3k6B/jG10CggEBAMxf2DoI5EAKRaUcUOHa
|
||||||
9kjzn376XKAsb02caixnTHK7Vuh7fq0sIThUUhT9mKBBbswRANtAv6Gz7YE4SPmf
|
fUxIFhl4p8HMPy7zVkORPt2tZLf8xz/z7mRRirG+7FlPetJj4ZBrr09fkZVtKkwJ
|
||||||
1+6nAAM2ve2zwlm3sWoAJfvF/W+qoJ+EUsJK+TO3J1yozdwPanYwS52t5UKKIUU3
|
9o8o7jGv2hSC9s/IFHb38tMF586N9nPTgenmWbF09ZHuiXEpSZPiJZvIzn/5a1Ch
|
||||||
k2jNge75GUmkCs1m58NHqoXc5PWKTtt4cf17LrJfaARdBe5Wjw3sVtdU+nE1mh+E
|
IHiKyPUYKm4MYvhmM/+J4Z5v0KzrgJXlWHi0GJFu6KfWyaOcbdQ4QWG6009XAcWv
|
||||||
8rcI8Sc2Yyes3Sf07Fw0+wb8fVPUAJPIM4JNK8XRfQJOnA4jr44GrPyLkqS0sw0p
|
Cbn5z9KlTvKKbFDMA+UyYVG6wrdUfVzC1V6uGq+/49qiZuzDWlz4EFWWlsNsRsft
|
||||||
kvtjcv75JLAKjN39da3sUDCctVf4h7Cy0jee5n1uVV3uAiP+6BX0D6tsWK34FEsG
|
Pmz5Mjglu+zVqoZJYYGDydWjmT0w53qmae7U2hJOyqr5ILINSIOKH5qMfiboRr6c
|
||||||
MZECggEBAIi/sjZNQjplD5zOULEWL8W6b+3CZymR5Qqa0brlx1Lz8h/daIITIFvm
|
GM0CggEAJTQD/jWjHDIZFRO4SmurNLoyY7bSXJsYAhl77j9Cw/G4vcE+erZYAhp3
|
||||||
bue/CjIht/oRGLVE8yzw2ojLf424h3h5PjmXMBNHlVkWQXfn6xCI8MjfZ71uA39O
|
LYu2nrnA8498T9F3H1oKWnK7u4YXO8ViyQd73ql7iKrMjE98CjfGcTPCXwOcPAts
|
||||||
RVCXAYwcghOWZL4Fkz+XQmIOdJ1OPXfU0py943joYZbgXXAYOc/zNylo9j7+bqDK
|
ZpM8ykgFTsJpXEFvIR5cyZ6XFSw2m/Z7CRDpmwQ8es4LpNnYA7V5Yu/zDE4h2/2T
|
||||||
vLtFd4IIQoRzjsY//FoAuAditf4xDRqLwOh4amboZw1Qmn6bwDnCaKsFmA3o5BYR
|
NmftCiZvkxwgj6VyKumOxXBnGK6lB+b6YMTltRrgD/35zmJoKRdqyLb1szPJtQuh
|
||||||
4aRUm1dEbZgPtm2tuHQpEKuOPhWHroi3NsEdbhoyy3IUe0c3w4YGgnuvVy616wkV
|
HjRTa/BVPgA66xYFWhifRUiYKpc0bARTYofHeoDgu6yPzcHMuM70NQQGF+WWJySg
|
||||||
GlPvUaKC1KX0CX1qT1anVZq9bSMTG+M=
|
vc3Za4ClKSLmb3ZA9giTswYMev+3BQ==
|
||||||
-----END PRIVATE KEY-----
|
-----END PRIVATE KEY-----
|
||||||
|
Binary file not shown.
@ -1,33 +1,33 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIFujCCA6KgAwIBAgIUOVccYETgo2YpKO85U4XRKifK09kwDQYJKoZIhvcNAQEL
|
MIIFujCCA6KgAwIBAgIUIP5CN0WpH5om1bGaFn17Xc5ITJIwDQYJKoZIhvcNAQEL
|
||||||
BQAwazELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMREwDwYDVQQHDAhTb21lQ2l0
|
BQAwazELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMREwDwYDVQQHDAhTb21lQ2l0
|
||||||
eTESMBAGA1UECgwJTXlDb21wYW55MRMwEQYDVQQLDApNeURpdmlzaW9uMRMwEQYD
|
eTESMBAGA1UECgwJTXlDb21wYW55MRMwEQYDVQQLDApNeURpdmlzaW9uMRMwEQYD
|
||||||
VQQDDAp3ZWIzc2lnbmVyMCAXDTIzMDkyMjAzMDA1NloYDzIxMjMwODI5MDMwMDU2
|
VQQDDAp3ZWIzc2lnbmVyMCAXDTIzMDkyMDAyNTYzNFoYDzIxMjMwODI3MDI1NjM0
|
||||||
WjBrMQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkExETAPBgNVBAcMCFNvbWVDaXR5
|
WjBrMQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkExETAPBgNVBAcMCFNvbWVDaXR5
|
||||||
MRIwEAYDVQQKDAlNeUNvbXBhbnkxEzARBgNVBAsMCk15RGl2aXNpb24xEzARBgNV
|
MRIwEAYDVQQKDAlNeUNvbXBhbnkxEzARBgNVBAsMCk15RGl2aXNpb24xEzARBgNV
|
||||||
BAMMCndlYjNzaWduZXIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCr
|
BAMMCndlYjNzaWduZXIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDS
|
||||||
JajqnvRQEREph+zu7rw1QjHQG1x2H44SJSMjX1Wzi9FErlRSOzywPFL2AzGsNvNS
|
cvshqu3747j4KMaGyGW0CA2GAznogVyKqNt4lan/8mdYUI2PUeezaUOnmoyM9oWz
|
||||||
tPmxN/kF9mBjQIQHxo90M4GcZgW1aljPaXLvQWFrP9ak+JjHuUG+j51fVJp8F2Qc
|
1FPflpj7pVWagWlSOgZ9vOElqQhe+la4ZEdGmOpe44c1rBoeHK314Gbmr2EuCxaa
|
||||||
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
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
@ -1,33 +1,33 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
MIIFujCCA6KgAwIBAgIUOVccYETgo2YpKO85U4XRKifK09kwDQYJKoZIhvcNAQEL
|
MIIFujCCA6KgAwIBAgIUIP5CN0WpH5om1bGaFn17Xc5ITJIwDQYJKoZIhvcNAQEL
|
||||||
BQAwazELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMREwDwYDVQQHDAhTb21lQ2l0
|
BQAwazELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMREwDwYDVQQHDAhTb21lQ2l0
|
||||||
eTESMBAGA1UECgwJTXlDb21wYW55MRMwEQYDVQQLDApNeURpdmlzaW9uMRMwEQYD
|
eTESMBAGA1UECgwJTXlDb21wYW55MRMwEQYDVQQLDApNeURpdmlzaW9uMRMwEQYD
|
||||||
VQQDDAp3ZWIzc2lnbmVyMCAXDTIzMDkyMjAzMDA1NloYDzIxMjMwODI5MDMwMDU2
|
VQQDDAp3ZWIzc2lnbmVyMCAXDTIzMDkyMDAyNTYzNFoYDzIxMjMwODI3MDI1NjM0
|
||||||
WjBrMQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkExETAPBgNVBAcMCFNvbWVDaXR5
|
WjBrMQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkExETAPBgNVBAcMCFNvbWVDaXR5
|
||||||
MRIwEAYDVQQKDAlNeUNvbXBhbnkxEzARBgNVBAsMCk15RGl2aXNpb24xEzARBgNV
|
MRIwEAYDVQQKDAlNeUNvbXBhbnkxEzARBgNVBAsMCk15RGl2aXNpb24xEzARBgNV
|
||||||
BAMMCndlYjNzaWduZXIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCr
|
BAMMCndlYjNzaWduZXIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDS
|
||||||
JajqnvRQEREph+zu7rw1QjHQG1x2H44SJSMjX1Wzi9FErlRSOzywPFL2AzGsNvNS
|
cvshqu3747j4KMaGyGW0CA2GAznogVyKqNt4lan/8mdYUI2PUeezaUOnmoyM9oWz
|
||||||
tPmxN/kF9mBjQIQHxo90M4GcZgW1aljPaXLvQWFrP9ak+JjHuUG+j51fVJp8F2Qc
|
1FPflpj7pVWagWlSOgZ9vOElqQhe+la4ZEdGmOpe44c1rBoeHK314Gbmr2EuCxaa
|
||||||
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
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
@ -1,52 +1,52 @@
|
|||||||
-----BEGIN PRIVATE KEY-----
|
-----BEGIN PRIVATE KEY-----
|
||||||
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
|
||||||
CXDusRSlsQNpzHc6QKq8IDZLut9g
|
oJ/aHbXf6PdOO9MYiI/es/dfKK8ywA==
|
||||||
-----END PRIVATE KEY-----
|
-----END PRIVATE KEY-----
|
||||||
|
Binary file not shown.
@ -1 +1 @@
|
|||||||
lighthouse FF:4C:84:A6:37:28:EC:7E:A7:D8:C6:49:0D:C6:F9:5D:C1:06:BA:6D:69:49:0A:AA:38:32:01:2B:ED:D9:F2:FA
|
lighthouse 02:D0:A8:C0:6A:59:90:40:54:67:D4:BD:AE:5A:D4:F5:14:A9:79:38:98:E0:62:93:C1:77:13:FC:B4:60:65:CE
|
||||||
|
@ -56,7 +56,7 @@ itertools = { workspace = true }
|
|||||||
monitoring_api = { workspace = true }
|
monitoring_api = { workspace = true }
|
||||||
sensitive_url = { workspace = true }
|
sensitive_url = { workspace = true }
|
||||||
task_executor = { workspace = true }
|
task_executor = { workspace = true }
|
||||||
reqwest = { workspace = true }
|
reqwest = { workspace = true, features = ["native-tls"] }
|
||||||
url = { workspace = true }
|
url = { workspace = true }
|
||||||
malloc_utils = { workspace = true }
|
malloc_utils = { workspace = true }
|
||||||
sysinfo = { workspace = true }
|
sysinfo = { workspace = true }
|
||||||
|
@ -6,20 +6,23 @@ ARCHIVE_URL := https://github.com/eth-clients/slashing-protection-interchange-te
|
|||||||
|
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
ifeq (, $(shell where rm))
|
ifeq (, $(shell where rm))
|
||||||
rmfile = if exist $(1) (del /F /Q $(1))
|
rmfile = if exist $(1) (del /F /Q $(1))
|
||||||
rmdir = if exist $(1) (rmdir /Q /S $(1))
|
rmdir = if exist $(1) (rmdir /Q /S $(1))
|
||||||
|
makedir = if not exist $(1) (mkdir $(1))
|
||||||
else
|
else
|
||||||
rmfile = rm -f $(1)
|
rmfile = rm -f $(1)
|
||||||
rmdir = rm -rf $(1)
|
rmdir = rm -rf $(1)
|
||||||
|
makedir = mkdir -p $(1)
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
rmfile = rm -f $(1)
|
rmfile = rm -f $(1)
|
||||||
rmdir = rm -rf $(1)
|
rmdir = rm -rf $(1)
|
||||||
|
makedir = mkdir -p $(1)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(OUTPUT_DIR): $(TARBALL)
|
$(OUTPUT_DIR): $(TARBALL)
|
||||||
$(call rmdir,$@)
|
$(call rmdir,$@)
|
||||||
mkdir $@
|
$(call makedir,$@)
|
||||||
tar --strip-components=1 -xzf $^ -C $@
|
tar --strip-components=1 -xzf $^ -C $@
|
||||||
|
|
||||||
$(TARBALL):
|
$(TARBALL):
|
||||||
|
@ -25,8 +25,10 @@ fn test_root_dir() -> PathBuf {
|
|||||||
.join("tests")
|
.join("tests")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: I've combined two tests together to avoid a race-condition which occurs when fighting over
|
||||||
|
// which test builds the TEST_ROOT_DIR lazy static.
|
||||||
#[test]
|
#[test]
|
||||||
fn generated() {
|
fn generated_and_with_minification() {
|
||||||
for entry in TEST_ROOT_DIR
|
for entry in TEST_ROOT_DIR
|
||||||
.join("generated")
|
.join("generated")
|
||||||
.read_dir()
|
.read_dir()
|
||||||
@ -37,10 +39,7 @@ fn generated() {
|
|||||||
let test_case: MultiTestCase = serde_json::from_reader(&file).unwrap();
|
let test_case: MultiTestCase = serde_json::from_reader(&file).unwrap();
|
||||||
test_case.run(false);
|
test_case.run(false);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn generated_with_minification() {
|
|
||||||
for entry in TEST_ROOT_DIR
|
for entry in TEST_ROOT_DIR
|
||||||
.join("generated")
|
.join("generated")
|
||||||
.read_dir()
|
.read_dir()
|
||||||
|
@ -1176,7 +1176,8 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
|
|||||||
.or(get_fee_recipient)
|
.or(get_fee_recipient)
|
||||||
.or(get_gas_limit)
|
.or(get_gas_limit)
|
||||||
.or(get_std_keystores)
|
.or(get_std_keystores)
|
||||||
.or(get_std_remotekeys),
|
.or(get_std_remotekeys)
|
||||||
|
.recover(warp_utils::reject::handle_rejection),
|
||||||
)
|
)
|
||||||
.or(warp::post().and(
|
.or(warp::post().and(
|
||||||
post_validators
|
post_validators
|
||||||
@ -1187,15 +1188,18 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
|
|||||||
.or(post_fee_recipient)
|
.or(post_fee_recipient)
|
||||||
.or(post_gas_limit)
|
.or(post_gas_limit)
|
||||||
.or(post_std_keystores)
|
.or(post_std_keystores)
|
||||||
.or(post_std_remotekeys),
|
.or(post_std_remotekeys)
|
||||||
|
.recover(warp_utils::reject::handle_rejection),
|
||||||
))
|
))
|
||||||
.or(warp::patch().and(patch_validators))
|
.or(warp::patch()
|
||||||
|
.and(patch_validators.recover(warp_utils::reject::handle_rejection)))
|
||||||
.or(warp::delete().and(
|
.or(warp::delete().and(
|
||||||
delete_lighthouse_keystores
|
delete_lighthouse_keystores
|
||||||
.or(delete_fee_recipient)
|
.or(delete_fee_recipient)
|
||||||
.or(delete_gas_limit)
|
.or(delete_gas_limit)
|
||||||
.or(delete_std_keystores)
|
.or(delete_std_keystores)
|
||||||
.or(delete_std_remotekeys),
|
.or(delete_std_remotekeys)
|
||||||
|
.recover(warp_utils::reject::handle_rejection),
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
// The auth route and logs are the only routes that are allowed to be accessed without the API token.
|
// The auth route and logs are the only routes that are allowed to be accessed without the API token.
|
||||||
|
@ -2146,7 +2146,7 @@ async fn import_remotekey_web3signer_enabled() {
|
|||||||
assert_eq!(tester.vals_total(), 1);
|
assert_eq!(tester.vals_total(), 1);
|
||||||
assert_eq!(tester.vals_enabled(), 1);
|
assert_eq!(tester.vals_enabled(), 1);
|
||||||
let vals = tester.initialized_validators.read();
|
let vals = tester.initialized_validators.read();
|
||||||
let web3_vals = vals.validator_definitions().clone();
|
let web3_vals = vals.validator_definitions();
|
||||||
|
|
||||||
// Import remotekeys.
|
// Import remotekeys.
|
||||||
let import_res = tester
|
let import_res = tester
|
||||||
@ -2164,7 +2164,7 @@ async fn import_remotekey_web3signer_enabled() {
|
|||||||
assert_eq!(tester.vals_total(), 1);
|
assert_eq!(tester.vals_total(), 1);
|
||||||
assert_eq!(tester.vals_enabled(), 1);
|
assert_eq!(tester.vals_enabled(), 1);
|
||||||
let vals = tester.initialized_validators.read();
|
let vals = tester.initialized_validators.read();
|
||||||
let remote_vals = vals.validator_definitions().clone();
|
let remote_vals = vals.validator_definitions();
|
||||||
|
|
||||||
// Web3signer should not be overwritten since it is enabled.
|
// Web3signer should not be overwritten since it is enabled.
|
||||||
assert!(web3_vals == remote_vals);
|
assert!(web3_vals == remote_vals);
|
||||||
|
Loading…
Reference in New Issue
Block a user